https://leetcode-cn.com/problems/qing-wa-tiao-tai-jie-wen-ti-lcof/
解题思路【 转自:https://leetcode-cn.com/problems/qing-wa-tiao-tai-jie-wen-ti-lcof/solution/jian-zhi-offerer-shua-javacong-di-gui-da-rp2h/ 仅做个人备份 浏览请看原文 】
和斐波那契数列问题一模一样
递归法
核心思想:怎么跳到第n阶台阶呢,由于一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶,所以青蛙可以从第n-1阶台阶跳一级来到第n阶,也可以第n-2阶台阶跳两级来到第n阶台阶。同样的,第n-1和第n-2也满足这个条件,本质就是递归问题。既然是递归就可以用树形结构表示。
以n=6为例
解题代码(超时)
class Solution {
public int numWays(int n) {
return Ways(n);
}
private int Ways(int n){
if(n <= 1){
return 1;
}
if( n == 2){
return 2;
}
return (Ways(n-1) % 1000000007) + (Ways(n-2) % 1000000007);
}
}
备忘录法
我们观察递归树,可以看到其实递归过程中我们做了很多重复性的工作
图中颜色相同的部分就是重复性的工作,所以为了缩短时间我们就需要避免重复性的工作。
减少重复的工作的方法就是将已经计算过的数值保存起来
这就是备忘录的核心工作,本质就是空间换时间
class Solution {
public int numWays(int n) {
int[] memo = new int[101];
// 备忘录初始化
memo[0] = 1;
memo[1] = 1;
memo[2] = 2;
return Ways(memo, n);
}
private int Ways(int[] memo, int n){
// 如果备忘录中已经存在值,直接返回已经记录的值
if(memo[n] !=0){
return memo[n];
}
memo[n] = (Ways(memo, n-1) + Ways(memo, n-2)) % 1000000007;
return memo[n];
}
}
动态规划
很明显,青蛙跳台阶的问题就是斐波那契数列问题
状态定义: 设 dpdp 为一维数组,其中 dp[i] 就是青蛙跳上一个 n 级的台阶总共跳法数
转移方程: dp[i + 1] = dp[i] + dp[i - 1] ,即对应数列定义 f(n + 1) = f(n) + f(n - 1) ;
初始状态: dp[0] = 1dp[0]=1, dp[1] = 1dp[1]=1 ,即初始化前三个数字;
返回值: dp[n] ,青蛙跳上一个 n 级的台阶跳法数
时间复杂度O(n),空间复杂度O(n)
解题代码
public class Solution {
public int numWays(int n) {
if (n == 0 || n == 1) {
return 1;
}
// 初始状态
int[] dp = new int[n + 1];
dp[1] = 1;
dp[2] = 2;
// 状态转移
for (int i = 3; i <= n; i++) {
dp[i] = (dp[i - 2] + dp[i - 1]) % 1000_000_007;
}
return dp[n];
}
}
动态规划的优化
其实很久状态转移方程我们也可以很清楚的看出来,dp[n]只跟前两项即dp[n-1], dp[n-2]有关,既然如此那么我们就不需要申请那么多空间,直接用两个变量来表示前两项就可以了。
时间复杂度O(n),空间复杂度O(1)
解题代码
public class Solution {
public int numWays(int n) {
if (n == 0 || n == 1) {
return 1;
}
// 两个变量表示前两项
int pre = 1, cur = 2;
for (int i = 3; i <= n; i++) {
int tmp = (pre + cur) % 1000_000_007;
// 更新变量,以便继续求解
pre = cur;
cur = tmp;
}
return cur;
}
}
func numWays(n int) int {
if n <= 1 {
return 1
}
per, cur := 1, 2
for i := 3; i <= n; i++ {
tmp := (per + cur) % 1000_000_007
per = cur
cur = tmp
}
return cur
}