一个机器人位于一个 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];
};
🧩 为什么是相加?(逻辑图解)
我们可以用一个小例子来手动推演:
假设是一个 的网格:
- 第一行和第一列全是
1。 - 坐标 (1,1) 的位置:左边来有
1种,上面来有1种, 种。 - 坐标 (1,2) 的位置:左边(刚才那个 2)来有
2种,上面来有1种, 种。
这其实就是数学里的**杨辉三角(Pascal's Triangle)**在矩形阵列里的应用。
💡 算法亮点
- 时间复杂度 :每一个路口只算一次。
- 空间复杂度 :用了一个和地图一样大的表格来存数据。