题目来源
分析
有 n 个台阶,设 n 个台阶有 dp[n] 种跳法,分情况:
- 青蛙跳 1 个台阶,剩下的 n-1 个台阶有 dp[n-1] 种跳法;
- 青蛙跳 2 个台阶,剩下的 n-2 个台阶有 dp[n-2] 种跳法。
由上找到状态之间的关系:
解法
1)按照上述形式,可以使用递归,即求 dp[n] 就是求 dp[n-1]、dp[n-2]。这里不展示代码了。
2)进一步分析,如 dp[5]=dp[3]+dp[4]、dp[4]=dp[3]+dp[2] …。可以看出,原问题分解为子问题时,出现子问题重复计算。我们可想着用一个变量保存以计算过的子问题,于是可以采用带有备忘录的递归算法。(代码略)。
3)该问题其实符合动态规划的问题,所以可以采用动态规划,使用 dp table。使用动态规划与带备忘录的递归算法从时间以及空间复杂度上是相等的。但是可以对动态规划的空间复杂度进行优化,使其为 O(1)。
优化思路:当前状态值是最近的两个状态值的和,与其他历史值无关,所以每次只要迭代记录邻近两个状态值即可。为什么带备忘录的递归算法不能这样优化,因为递归是函数调用函数,类似深度优先搜索原则,只有子问题 dp[n-1] 计算完结果才会执行子问题 dp[n-2] 计算结果。如果不记录子问题 dp[n-1] 中的多个中间值,子问题 dp[n-2] 就会重复计算。
代码如下:
class Solution {
public int numWays(int n) {
// 动态规划优化
if(n<=1){
return 1;
}
// 使用两个单变量代替状态数组。
int pre = 1;
int next = 1;
int res = 0;
for(int i=2; i<=n; i++){
res = (pre + next) % 1000_000_007 ;
pre = next;
next = res;
}
return res;
}
}
本文详细解析了青蛙跳台阶问题的解决方法,通过递归、带备忘录的递归及动态规划三种方式来求解,并针对动态规划进行了空间优化。

754

被折叠的 条评论
为什么被折叠?



