62. 不同路径
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
问总共有多少条不同的路径?
例如,上图是一个7 x 3 的网格。有多少可能的路径?
说明:m 和 n 的值均不超过 100。
示例 1:
输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向右 -> 向下
2. 向右 -> 向下 -> 向右
3. 向下 -> 向右 -> 向右
示例 2:
输入: m = 7, n = 3
输出: 28
思路
必须要向下走n-1格向右走m-1格,第一时间想到的是 Cmn+m−2 C n + m − 2 m 个排列组合,思路是没有错,但是后面的计算出现了很多问题。
第一个程序
完全的按照 Cmn+m−2 C n + m − 2 m 来计算,求它的阶乘再相除,结果就是用了long long也还是超出了数值范围,导致结果不正确。
class Solution {
public:
int uniquePaths(int m, int n) {
--m;--n;
if(m==0){return n;}
if(n==0){return m;}
int res = CNM(n+m,n);
return res;
}
long CNM(int t,int n){
if(n==0){return t;}
long long res1 = ANM(t);
long long res2 = ANM(n);
long long res3 = ANM(t-n);
return res1/(res2*res3);
}
long long ANM(int x){
if(x<=1){return 1;}
return x*ANM(x-1);
}
};
第二个程序
想到可以转换C(n, k) = C(n-1, k-1) + C(n-1, k),于是用了递归来计算组合,想了下全是加法应该没有问题,但是最后还是超时了。
class Solution {
public:
int uniquePaths(int m, int n) {//C(n, k) = C(n-1, k-1) + C(n-1, k),
--m;--n;
if(m==0||n==0){return 1;}
int res = CNM(n+m,n);
return res;
}
long CNM(int t,int n){
if(n==0){return 1;}
if(t==n){return 1;}
return CNM(t-1,n-1)+CNM(t-1,n);
}
};
第三个程序
还得用我们老祖宗的东西来做,杨辉三角:
第n行的m个数可表示为 C(n-1,m-1),即为从n-1个不同元素中取m-1个元素的组合数。刚好就是题目所要求的一模一样。
class Solution {
public:
int uniquePaths(int m, int n) {
if (m == 0 || n == 0) {
return 0;
}
vector<vector<int>> path(m,vector<int>(n,0));
for (int i = 0; i < m; i++)
path[i][0] = 1;
for (int i = 0; i < n; i++)
path[0][i] = 1;
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
path[i][j] = path[i-1][j] + path[i][j-1];
}
}
return path[m-1][n-1];
}
};