【中等】62. 不同路径

0 阅读3分钟

一个机器人位于一个 m x n **网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

示例 1:

输入: m = 3, n = 7
输出: 28

示例 2:

输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右
3. 向下 -> 向右 -> 向下

示例 3:

输入: m = 7, n = 3
输出: 28

示例 4:

输入: m = 3, n = 3
输出: 6

提示:

  • 1 <= m, n <= 100
  • 题目数据保证答案小于等于 2 * 109

🏠 生活案例:外卖小哥的路线选择

想象你是一名外卖小哥,要去给住在城市右下角(Finish)的客户送餐。

  • 你站在左上角(Start)。
  • 这里的街道非常规整,像个棋盘。
  • 公司规定:为了效率,你只能向右走或者向下走,绝对不能绕路回头。

题目问的是:从你家到客户家,一共有多少条不同的走法?


💻 代码实现与生活化注释

这段代码的核心思想是: “通往某个路口的走法数量 = 通往它上边路口的走法 + 通往它左边路口的走法”

JavaScript

/**
 * @param {number} m
 * @param {number} n
 * @return {number}
 */
var uniquePaths = function(m, n) {
    // 1. 准备一张“路线统计表” dp[m][n]
    // dp[i][j] 表示到达坐标 (i, j) 这个路口总共有多少种走法
    let dp = new Array(m).fill(0).map(() => Array(n).fill(0));

    // 2. 初始化最左边的一列
    // 因为只能向下走,所以到达最左边那一排路口的走法永远只有 1 条(直线向下)
    for(let i = 0; i < m; i++){
        dp[i][0] = 1;
    }

    // 3. 初始化最上面的一行
    // 因为只能向右走,所以到达最上面那一排路口的走法永远只有 1 条(直线向右)
    for(let j = 0; j < n; j++){
        dp[0][j] = 1;
    }

    // 4. 计算中间路口的可能性
    for(let i = 1; i < m; i++){
        for(let j = 1; j < n; j++){
            // 核心逻辑:
            // 到达当前路口 (i, j),要么是从 [上边] 踩下来的,要么是从 [左边] 迈过来的
            // 所以总走法 = 上边的走法总数 + 左边的走法总数
            dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
        }
    }

    // 5. 最终右下角那个格子存的数字,就是所有可能的路径总数
    return dp[m - 1][n - 1];
};

🧩 为什么是相加?(逻辑图解)

我们可以用一个小例子来手动推演:

假设是一个 3×33 \times 3 的网格:

  1. 第一行和第一列全是 1
  2. 坐标 (1,1) 的位置:左边来有 1 种,上面来有 1 种, 1+1=21 + 1 = 2 种。
  3. 坐标 (1,2) 的位置:左边(刚才那个 2)来有 2 种,上面来有 1 种, 2+1=32 + 1 = 3 种。

这其实就是数学里的**杨辉三角(Pascal's Triangle)**在矩形阵列里的应用。


💡 算法亮点

  • 时间复杂度 O(m×n)O(m \times n) :每一个路口只算一次。
  • 空间复杂度 O(m×n)O(m \times n) :用了一个和地图一样大的表格来存数据。