我的想法:递归
根据观察,走到最后一步前到达最后一格的上方或者左边。所以规律为uniquePaths(m,n)=uniquePaths(m-1,n)+uniquePaths(m,n-1)
,因此可以得到如下代码:
class Solution {
public:
int uniquePaths(int m, int n) {
int result;
if (m==1||n==1)
return 1;
else
{
result=uniquePaths(m-1,n)+uniquePaths(m,n-1);//动态规划
return result;
}
}
};
运行结果:有部分用例超时
我的AC算法:动态规划
之前的递归算法没有保留中间子问题的结果,每次都需要调用和重新计算,可以采用动态规划进行优化。保存中间子问题结果,所以规模大一点的时候动态规划效果好。
class Solution {
public:
int uniquePaths(int m, int n) {
int dp[m+1][n+1]; //为了d[m][n]保存的是uniquePaths的结果,不从0开始使用
for(int i=1;i<=m;i++)
dp[i][1]=1;
for(int j=1;j<=n;j++)
dp[1][j]=1;
for(int i=2;i<=m;i++)
for(int j=2;j<=n;j++)
{
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
return dp[m][n];
}
};
最优解法
类似的思想,但是只保留一个一维数组,因为每次更新时dp[j] += dp[j - 1];
,更新之前dp[j]
为上一行对应列的值,dp[j-1]
为本行左边一列的值,相当于按行进行更新。
back()
函数返回当前vector
最末一个元素的引用。
class Solution {
public:
int uniquePaths(int m, int n) {
vector dp(n + 1, 0);//这一步的初始化巧妙地将边界问题解决了,左边界dp[0]和上边界dp初始化的值,将 dp[j] += dp[j - 1];可能的边界问题考虑进去了
dp[1] = 1;
for (int i = 0; i < m; ++i) {//行数
for (int j = 1; j <= n; ++j) {//列数
dp[j] += dp[j - 1];
}
}
return dp.back();
}
};