思想:
方法一:DP
时间复杂度O(n^2),空间复杂度O(n^2)
递推方程:
map[0][i] = 1; 0<=i<n
map[i][0] = 1; 0<=i<m
map[i][j] = map[i-1][j] + map[i][j-1]
最后结果 = map[i-1][j-1]
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> map(m,vector<int>(n,1));
for(int i=1;i<m;i++) {
for(int j=1;j<n;j++) {
map[i][j] = map[i-1][j] + map[i][j-1];
}
}
return map[m-1][n-1];
}
};
方法二:DP+滚动数组
时间复杂度O(n^2),空间复杂度O(n)
用一个一维滚动数组代替上面的二维数组,让这个一维数组从1到m-1往下刷,每一次更新其中的每一列的值,因为往下刷的时候记住了上一行的每一列的值,所以将:
map[i][j] = map[i-1][j] + map[i][j-1] 转为了 map[j] = map[j] + map[j-1]
class Solution {
public:
int uniquePaths(int m, int n) {
vector<int> map(n,1);
for(int i=1;i<m;i++) {
for(int j=1;j<n;j++) {
map[j]+=map[j-1];
}
}
return map[n-1];
}
};
方法三:DFS
但是TLE,由此想到记录每一个走过的点(备忘录)。
class Solution {
public:
int uniquePaths(int m, int n) {
if(m == 0 || n == 0) return 1;
return uniquePaths(m-1, n) + uniquePaths(m, n-1);
}
};
方法四:DFS+备忘录
初始条件:
map[0][i] = 1; 0<=i<n
map[i][0] = 1; 0<=i<m
map[i][j] = 0; others i,jdfs时候记录走过的点的map值。
class Solution {
private:
vector<vector<int>> map;
int dfs(int m,int n) {
if(m == 0 || n == 0) return 1;
return getOrUpdate(m-1, n) + getOrUpdate(m, n-1);
}
int getOrUpdate(int m,int n) {
if(map[m][n]!=0) return map[m][n];
else return map[m][n] = dfs(m,n);
}
public:
int uniquePaths(int m, int n) {
this->map = vector<vector<int>>(m,vector<int>(n,0));
return dfs(m-1,n-1);
}
};