剑指 Offer 10- II. 青蛙跳台阶问题

题目描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。

答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

示例 1:

1
2
输入:n = 2
输出:2

示例 2:

1
2
输入:n = 7
输出:21

示例 3:

1
2
输入:n = 0
输出:1

提示:

  • 0 <= n <= 100

解题思路

这道题是一道很经典的动态规划的题。

基本思路就是用动态数组中的元素dp[i]表示跳到i级台阶共有多少种跳法。那么我们可以很容易得到状态转移方程:

1
dp[i] = dp[i-1] + dp[i-2]     //因为一次只能跳一阶或者两阶台阶

然后边界条件就是跳到0级台阶的情况:

1
dp[0] = 1

然后照此思想编程就可以了。

但是这里有一个问题需要注意,在台阶数很大的情况下,用int、long、long long可能都会溢出,由于输出的时候需要取模,所以我们可以用下述公式避免数据溢出的问题:

1
(a + b) % c = (a % c + b % c ) % c

示例代码

1
2
3
4
5
6
7
8
9
10
int numWays(int n){
vector<int> dp(n + 1, 0);
dp[0] = 1;

for(int i = 1; i <= n; ++i){
dp[i] = dp[i - 1] % 1000000007 + (i >= 2 ? dp[i - 2] % 1000000007 : 0);
}

return dp[n] % 1000000007;
}

然后发现这里用一个数组去存储中间结果有些浪费空间,我们只需要用两个数来存储dp[i - 1] % 1000000007dp[i - 2] % 1000000007就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int numWays(int n){
int a = 1;
int b = 1;

if(n == 0 || n == 1) return 1;

for(int i = 2; i <= n; ++i){
int t = (a % 1000000007 + b % 1000000007) % 1000000007;
b = a;
a = t;
}

return a;
}

复杂度分析

时间复杂度:O(n)O(n)

空间复杂度:O(n)O(n),如果是第二个方法的话,空间复杂度是O(1)O(1)