地址:https://leetcode-cn.com/problems/unique-paths/
方法一:动态规划
-
状态:
dp[i][j]
表示走到坐标(i, j)
的路径总数; -
状态转移方程:思路依然是分类讨论,走到坐标
(i, j)
可以从上方下来,也可以从左边过来,路径总数是二者之和;
dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
-
初始化:数组
dp
的第 1 行和第 1 列都得显示赋值为 1; -
输出:
dp[m - 1][n - 1]
。 -
状态压缩:可以滚动数组,也可以只压缩到一维。
Java 代码:
import java.util.Arrays;
public class Solution {
public int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
Arrays.fill(dp[0], 1);
for (int i = 1; i < m; i++) {
dp[i][0] = 1;
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[m - 1][n - 1];
}
}
初始化的时候比较麻烦,因此可以考虑“哨兵”写法,将数组 dp
多写一行,多写一列。
Java 代码:
import java.util.Arrays;
public class Solution {
public int uniquePaths(int m, int n) {
int[][] dp = new int[m + 1][n + 1];
// 初始化的时候 dp[0][1] = 1; 或者 dp[1][0] = 1; 均可
dp[1][0] = 1;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
dp[i + 1][j + 1] = dp[i][j + 1] + dp[i + 1][j];
}
}
return dp[m][n];
}
}
状态压缩。
Java 代码:
public class Solution {
public int uniquePaths(int m, int n) {
int[] dp = new int[n];
dp[0] = 1;
for (int i = 0; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[j] += dp[j - 1];
}
}
return dp[n - 1];
}
}
方法二:组合数
使用组合数来求解,走到坐标为 (m, n)
的地方,向下走 m - 1
格,向右边走 n - 1
格。一共走 m + n - 2
格。