[每日算法 - 华为机试] 剑指 Offer 10- II. 青蛙跳台阶问题
入口
力扣
https://leetcode.cn/problems/qing-wa-tiao-tai-jie-wen-ti-lcof/
题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
示例 1:
输入:n = 2
输出:2
示例 2:输入:n = 7
输出:21
示例 3:输入:n = 0
输出:1
提示:0 <= n <= 100
斐波那契数列
青蛙跳台阶问题是一种经典的动态规划问题,可以通过类比斐波那契数列来求解。问题的关键在于理解青蛙跳跃的可能路径:
-
第1级台阶:只有 1 种方法,即青蛙直接跳1级到达目标。
-
第2级台阶:有 2 种方法:
- 跳1级,然后再跳1级:青蛙可以选择先跳到第1级台阶,然后再跳1级到第2级。
- 直接跳2级:青蛙可以选择直接从地面跳到第2级。
-
第n级台阶(n > 2):对于任意第n级台阶,青蛙有两种可能的最后一步:
- 从第(n-1)级台阶跳1级:青蛙可以先跳到第(n-1)级台阶,然后再跳1级到达第n级。
- 从第(n-2)级台阶跳2级:青蛙可以先跳到第(n-2)级台阶,然后直接跳2级到达第n级。
这个思路的核心在于,每个台阶的到达方法数是基于前两个台阶的方法数之和,因为青蛙可以选择跳1级或者2级。
递推公式:F(n) = F(n-1) + F(n-2)
方法一:递归
Java示例
class Solution {
public int climbStairs(int n) {
if(n==1 || n==2){
return n;
}
return climbStairs(n-1) + climbStairs(n-2);
}
}
时间复杂度:O(2^n)
空间复杂度:O(n)
方法二:记忆递归
方法一缺点: 多了很多重复计算(如红框圈出来的地方),记忆递归的讲每次计算结果存储,不再重复计算。
方法一复杂度分析Java示例
class Solution {
public int climbStairs(int n) {
int memo[] = new int[n+1];//存储计算结果
return climb(memo,n);
}
public int climb(int[] memo,int n){
if(n==1 || n==2){
memo[n] = n;
}
if(memo[n] == 0){
memo[n] = climb(memo,n-1) + climb(memo,n-2);
}
return memo[n];
}
}
时间复杂度:O(n)
空间复杂度:O(n)
方法三:动态规划
Java示例
class Solution {
public int climbStairs(int n) {
if(n==1 || n==2){
return n;
}
int dp[] = new int[n+1];
dp[1] = 1;
dp[2] = 2;
for(int i=3;i<=n;i++){
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n-1] + dp[n-2];
}
}
时间复杂度:O(n)
空间复杂度:O(n)
方法四:斐波那契数列
在方法一的dp数组中只有两个元素被使用,现在将浪费的空间优化掉,将空间复杂度降为O(1)
Java示例
class Solution {
public int climbStairs(int n) {
if(n==1 || n==2){
return n;
}
int first=1;
int second = 2;
for(int i=3;i<n;i++){
int third = first + second;
first = second;
second = third;
}
return first + second;
}
}
时间复杂度:O(n)
空间复杂度:O(1)

浙公网安备 33010602011771号