【Leetcode】62.不同路径

62. 不同路径

题目

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

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

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

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

注意:如果把网格看成矩阵的话,m为列数,n为行数

方法(动态规划)

  • 设$dp[i,j]$为从左上角开始,到达点(i,j)的所有可能路径数。由题意可知,若想到达一个点,只能从该点的上方或者左方到达。因此有如下状态转移方程:
    $$ dp[i,j] = dp[i-1,j] + dp[i, j-1]$$

  • 确定base case:

    • 对于网格第一列上的所有点(j = 0),若想到达它,只能从上方到达,即:
      $$ dp[i,j] = dp[i-1,j]$$
    • 对于网格第一行上的所有点(i = 0),若想到达它,只能从左方到达,即:
      $$dp[i,j] = dp[i, j-1]$$
    • 对于网格左上角的点,dp[0,0] = 1;

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public int uniquePaths(int m, int n) {
if(m == 1 || n == 1)
return 1;
int[][] dp = new int[n][m];
//设置base case
dp[0][0] = 1;
for(int j = 1; j < m; j++)
dp[0][j] = dp[0][j - 1];
for(int i = 1; i < n; i++)
dp[i][0] = dp[i - 1][0];
//填写dp数组
for(int i = 1; i < n; i++){
for(int j = 1; j < m; j++)
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
return dp[n - 1][m - 1];
}

方法(数学)

机器人要从左上角走到右下角,需要向右走n-1步,向下走m-1步,总共需要走m+n-2步。

我们要找路径数,也就是要找在这m + n - 2步中,选择n - 1步向右走的方案数。即:
$$
C_{m+n-2}^{n-1}=\frac{(m+n-2) !}{(n-1) !(n-1) !}
$$

1
2
3
4
5
6
7
public int uniquePaths(int m, int n) {
int N = n + m - 2;
double res = 1;
for (int i = 1; i < m; i++)
res = res * (N - (m - 1) + i) / i;
return (int) res;
}