leetcode : 62. 不同路径
一个机器人位于一个 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
Related Topics
数学
动态规划
组合数学
思路1:递归
每次计算向右和向下的路径和,返回。
经过测试,超时,因为计算的很多重复的点。
class Solution {
private int m;
private int n;
public int uniquePaths(int m, int n) {
this.m = m;
this.n = n;
return fun(1,1);
}
public int fun(int i, int j){
if(i == m && j == n){
return 1;
}
//向右
int right = 0;
if(j < n){
right = fun(i,j+1);
}
//向下
int down = 0;
if(i < m){
down = fun(i+1,j);
}
return right+down;
}
}//超时
思路2:动态规划(从右下角往左上角递归)
思路1 的修改,举例说明,要计算P(0,0) = P(1,0)+P(0,1)。我们计算P(1,0)时,需要计算P(1,1)。计算P(0,1)时,也需要计算P(1,1)。导致计算重复,思路1超时。
可以使用动态规划的思路,将递归时计算的P(i,j)保存,如果这个值已经计算出来,那么直接拿出来,如果没计算,再递归,这样每一个位置只会计算一次。
class Solution {
//m ,n表示终点的下标
private int m;
private int n;
private int[][] dp;
public int uniquePaths(int m, int n) {
this.m = m-1;
this.n = n-1;
dp = new int[m][n];
return fun(0,0);
}
public int fun(int i, int j){
if(i == m && j == n){
dp[m][n] = 1;
return 1;
}
//向右 如果i,j+1已经计算过 就直接返回
int right = 0;
if(j < n){
right = dp[i][j+1] == 0 ? fun(i,j+1) : dp[i][j+1];
}
//向下
int down = 0;
if(i < m){
down = dp[i+1][j] == 0 ? fun(i+1,j) : dp[i+1][j];
}
dp[i][j] = right+down;
return dp[i][j];
}
}
解答成功:
执行耗时:0 ms,击败了100.00% 的Java用户
内存消耗:38 MB,击败了30.59% 的Java用户
思路3: 动态规划(从左上角往右上角计算)
参考leetcode官方:计算0,0点每一个点的路径和。
分析:P(i,j) = P(i-1,j) + P(i,j-1)
-
从0,0点开始计算,但是i-1和j-1可能会越界。
-
从0,0开始到第一行的任意一个点的路径只有1个,同理,到第一列的任意一个点路径只有1个。这样就可以解决越界问题。
class Solution {
//m ,n表示终点的下标
public int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
//第一列
for(int i = 0 ; i < m;i++){
dp[i][0] = 1;
}
//第一行
for(int j = 0 ; j < n;j++){
dp[0][j] = 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];
}
}
解答成功:
执行耗时:0 ms,击败了100.00% 的Java用户
内存消耗:38.3 MB,击败了10.63% 的Java用户
思路4:组合数学
从左上角到右下角的过程中,我们需要移动 m+n−2 次,其中有 m−1 次向下移动,n−1 次向右移动。因此路径的总数,就等于从 m+n−2 次移动中选择 m−1 次向下移动的方案数,即组合数:C(m-1,m+n-2) = (m+n-2)(m+n-1).....n/(m-1)(m-2)....1
public int uniquePaths(int m, int n) {
long ans = 1;
int i = n;
int j = 1;
//注意 ans*i可能会越界 需要long解决越界问题
while (j < m){
ans = ans * i / j;
i++;
j++;
}
return (int)ans;









