思路一:记忆化搜索
class Solution {
public:
map<pair<int, int>, int> umap;
int dfs(int x, int y) {
if (x == 0 || y == 0) return 1;
if (umap.count({x, y})) return umap[{x, y}];
return umap[{x, y}] = dfs(x, y - 1) + dfs(x - 1, y);
}
int uniquePaths(int m, int n) {
return dfs(m - 1, n - 1);
}
};
易错点:
不能用unordered_map<pair<int, int>, int> umap;
思路二:dp ---------->O(m*n)
dp[i][j]表示 [0][0]到达[i][j]的路径数
转移方程:dp[i][j]=dp[i-1][j]+dp[i-1][j]
初始化:dp[0][…] = 1
class Solution {
public:
int uniquePaths(int n, int m) {
vector<int> dp(m);
dp[0] = 1;
for (int i = 0; i < n; ++i) {
for (int j = 1; j < m; ++j) {
dp[j] = dp[j] + dp[j - 1];
}
}
return dp[m - 1];
}
};
思路三:数学
从左上角到右下角的过程中,需要移动m+n−2 次,其中有 m−1 次向下移动,n−1 次向右移动。因此路径的总数等于从m+n−2 次移动中选择 m-1次向下移动的方案数.
分子分母都是m-1个
class Solution {
public:
int uniquePaths(int m, int n) {
//求组合数模板
long long ans = 1; //
int x = n, y = 1;
for (int i = 0; i < m - 1; ++i) { //
ans = ans * x / y;
x++;
y++;
}
return ans;
}
};
易错点:
1:从小往大写,不然容易越long long界!!!
为什么每次必能整除?
因为每个2个数,有一个肯定是2的倍数
每隔3个数,有一个是3的倍数
每隔4个数有一个是4的倍数
…