算法学习Day39不同路径
Day39不同路径
By HQWQF 2024/01/22
笔记
62.不同路径
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
示例 1:
输入:m = 3, n = 7
输出:28
动态规划
对于任意一个位置,到达该位置的路径数等于到达该位置上方和左方位置的路径数之和。
边界上的位置到达路径数都是1,需要初始化。
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> dp(m, vector<int>(n, 0));
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];
}
};
组合数法
应用高中数学,我们知道到达右下角必须向下走m-1步和向右n-1步,假设总共走n步。
所以这n步里必须有k步是向下的,所以n就是组合数c m-1 m+n-2。
分子和分母可以直接抵消一部分,所以我们将从大到小阶乘,对分子阶乘m - 1或n - 1次,剩下的都被抵消了。
公式为:
C(m+n−2,m−1)=
(m−1)!(n−1)!/(m+n−2)!
但是我们知道计算组合数里的阶乘是容易溢出的,所以需要有特殊的处理。
直观的代码,会溢出:
class Solution {
public:
int uniquePaths(int m, int n) {
int numerator = 1, denominator = 1;
int count = m - 1;
int t = m + n - 2;
while (count--) numerator *= (t--); // 计算分子,此时分子就会溢出
for (int i = 1; i <= m - 1; i++) denominator *= i; // 计算分母
return numerator / denominator;
}
};
需要在计算分子的时候,不断除以分母
class Solution {
public:
int uniquePaths(int m, int n) {
long long numerator = 1; // 分子
int denominator = m - 1; // 分母,可为n-1
int count = m - 1;//可为n-1
int t = m + n - 2;
while (count--) {
numerator *= (t--);
while (denominator != 0 && numerator % denominator == 0) {
numerator /= denominator;
denominator--;
}
}
return numerator;
}
};