LeetCode-062不同路径,走法数怎么算?

摘要:本题在线练习:LeetCode 62. 不同路径 - 在线练习(免费 · 无需登录 · AI 辅助)(https:onefly.topzero2Leetcodeplayground
本题在线练习:LeetCode 62. 不同路径 - 在线练习(免费 · 无需登录 · AI 辅助)(https://onefly.top/zero2Leetcode/playground.html?id=62) 配套刷题网站 Zero2Leetcode —— 内置本地 OJ + AI 教练,零门槛开始刷 Hot 100。 题目概述 在一个 m x n 的网格中,机器人从左上角出发,每一步只能 向右 或 向下,问到达右下角一共有多少条不同路径。 这题看起来是“走迷宫”,但本质是一个非常典型的动态规划入门题:每个格子的路径数只取决于它的“上方”和“左方”。 核心思路:到达 (i, j) 的路径数从哪里来 设 dp[i][j] 表示到达格子 (i, j) 的不同路径数(i 从 0 到 m-1,j 从 0 到 n-1)。 到达 (i, j) 只有两种最后一步: 从上方 (i-1, j) 向下走一步 从左方 (i, j-1) 向右走一步 所以转移方程很自然: dp[i][j] = dp[i-1][j] + dp[i][j-1] 边界条件: 第一行只能一直向右走:dp[0][j] = 1 第一列只能一直向下走:dp[i][0] = 1 先从最自然的版本讲起:二维 DP 二维 DP 直观,便于理解“上方 + 左方”的含义。 代码实现(二维 dp) class Solution: def uniquePaths(self, m: int, n: int) -> int: dp = [[0] * n for _ in range(m)] for i in range(m): dp[i][0] = 1 for j in range(n): dp[0][j] = 1 for i in range(1, m): for j in range(1, n): dp[i][j] = dp[i - 1][j] + dp[i][j - 1] return dp[m - 1][n - 1] 逐行拆解:为什么这样填表 dp[i][0] = 1:在第一列,想从 (0,0) 到 (i,0) 只能一直向下,没有分岔。 dp[0][j] = 1:在第一行同理,只能一直向右。 从 (1,1) 开始填表:每个格子都能从上或左到达,路径数就是两者之和。 手动模拟:m=3, n=7 的“填表过程” 初始化第一行/列为 1: 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 从 (1,1) 开始: dp[1][1] = 1 + 1 = 2 dp[1][2] = 1 + 2 = 3 ... 最终会得到右下角的答案。 进阶:空间优化到一维 DP(更推荐的写法) 观察转移:dp[i][j] 只依赖“上一行同列”和“当前行前一列”。如果用一维数组 dp[j] 表示当前行的结果: dp[j] 在更新前是上一行的 dp[i-1][j] dp[j-1] 已经是当前行的 dp[i][j-1] 所以: dp[j] = dp[j] + dp[j-1] 代码实现(一维 dp) class Solution: def uniquePaths(self, m: int, n: int) -> int: dp = [1] * n # 第一行全是 1 for _ in range(1, m): for j in range(1, n): dp[j] = dp[j] + dp[j - 1] return dp[-1] 复杂度分析 二维 DP:时间 O(mn),空间 O(mn) 一维 DP:时间 O(mn),空间 O(n) 对比与总结 这题最值得带走的不是“背下代码”,而是这句话: “走到一个格子的路径数 = 走到它上面格子的路径数 + 走到它左边格子的路径数。” 掌握这个“从最后一步倒推”的思考方式,后面大量网格 DP(最小路径和、不同路径 II 等)都会非常顺。 结尾 不同路径是网格 DP 的标准起点。把 dp[i][j] 的定义说清楚、把边界条件想明白,再写代码就只是把逻辑翻译成循环而已。