LeetCode-062:不同路径,把“到达当前格子的走法数”想清楚就够了

本题在线练习: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-1j 从 0 到 n-1)。

到达 (i, j) 只有两种最后一步:

  1. 从上方 (i-1, j) 向下走一步
  2. 从左方 (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]

逐行拆解:为什么这样填表

  1. dp[i][0] = 1:在第一列,想从 (0,0)(i,0) 只能一直向下,没有分岔。
  2. dp[0][j] = 1:在第一行同理,只能一直向右。
  3. (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] 的定义说清楚、把边界条件想明白,再写代码就只是把逻辑翻译成循环而已。

posted @ 2026-03-27 01:18  孤飞  阅读(74)  评论(0)    收藏  举报