一、题目描述


二、解题思路
(1)解法一:深度优先搜索
1>函数功能:dfs函数用于从(i,j)位置开始,寻找到达终点(m-1,n-1)的路径条数;
2>递归出口:当i==m-1&&j==n-1时,表示找到了一条路径,ret++,然后return;
3>函数体:按照下、右的顺序进行探索,如果(x,y)未越界就对(x,y)位置递归调用dfs函数。
(2)解法二:直接递归
由于只能向下和向右走,所以只有从上面块和左边块才能到达现在所在的块,uniquePaths(i,j)表示到达(i,j)位置的路径的数量,则uniquePaths(i,j)=uniquePaths(i-1,j)+uniquePaths(i,j-1)。
(3)解法三:记忆化搜索
由于解法二在计算的过程中存在大量的重复计算,所以可以采用记忆化搜索的方法,把计算的结果记录下来,避免重复计算。
(4)解法四:动态规划
dp[i][j]的值表示从(0,0)到终点(i,j)的路径的条数,dp[i][j]=dp[i-1][j]+dp[i][j-1];
三、代码实现
解法一:深度优先搜索(超时)
cpp
class Solution {
int ret=0;
public:
int uniquePaths(int m, int n) {
dfs(0,0,m,n);
return ret;
}
int dx[2]={1,0};
int dy[2]={0,1};
void dfs(int i,int j,int m,int n){
//递归出口
if(i==m-1&&j==n-1){
ret++;
return ;
}
for(int k=0;k!=2;k++){
int x=i+dx[k];
int y=j+dy[k];
if(x>=0&&x<m&&y>=0&&y<n)
dfs(x,y,m,n);
}
}
};
解法二:直接递归(超时)
cpp
class Solution {
public:
int uniquePaths(int m, int n) {
//边界处理
if(m==1||n==1) return 1;
return uniquePaths(m-1,n)+uniquePaths(m,n-1);
}
};
解法三:记忆化搜索
cpp
class Solution {
vector<vector<int>> memo;
public:
int uniquePaths(int m, int n) {
//边界处理
if(m==1||n==1) return 1;
memo.resize(m+1,vector(n+1,-1));
for(int i=0;i<=n;i++) memo[0][i]=1;
for(int j=0;j<=m;j++) memo[j][0]=1;
return dfs(m-1,n-1);
}
int dfs(int m,int n){
//查找备忘录
if(memo[m][n]!=-1) return memo[m][n];
else{
memo[m][n]=dfs(m-1,n)+dfs(m,n-1);
return memo[m][n];
}
}
};
解法四:动态规划
cpp
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> dp(m,vector(n,-1));
//填写dp数组
for(int i=0;i!=m;i++) dp[i][0]=1;
for(int j=0;j!=n;j++) dp[0][j]=1;
for(int row=1;row!=m;row++)
for(int col=1;col!=n;col++)
dp[row][col]=dp[row-1][col]+dp[row][col-1];
return dp[m-1][n-1];
}
};