您的位置:首页 > Web前端

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

2021-11-27 13:28 239 查看

题目

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

思路1(递归 / 自顶向下)

这题就是和上一题剑指 Offer 10- I. 斐波那契数列基本一模一样,都是

fib(n) = fib(n-1) + fib(n-2)
这个递推公式,只是初始条件不一样啦:上一题是
0、1、1、2...
,而本题是
1、1、2、3、5...

  • 这题是很常见的一道入门递归题,可以采用自顶向下的递归方法,比如我们要求第

    n
    个位置的值,根据斐波那契数列的定义
    fib(n) = fib(n-1) + fib(n-2)
    ,即等于前一个和前前一个两个的值之和

  • 但是如果直接递归,会导致很多重复的计算,效率很低,比如

    n
    为 5 时:

      fib(5)
      fib(4)
      fib(3)
      两个值之和

    1. 然后

      fib(4)
      又等于
      fib(3)
      fib(2)
      两个值之和。注意,
      fib(3)
      在上一步已经求过了,这里还要再求一次

    2. 另一个

      fib(3)
      即为
      fib(2)
      fib(1)
      两个值之和,同样,
      fib(2)
      ,也被求过了

    3. ……

  • 根据上面例子我们可以发现这样子会导致很多多余的计算,做无用功,也会出现由于

    n
    的增大导致计算量急剧增大。因此我们可以将这个算法优化一下,就是添加一个表格
    memory
    来记录计算过的值,在每次递归的时候,判断一下之前是否计算过了,如果发现计算过了,直接返回数组中对应的值,否则就计算一下,然后记录到
    memory
    表格里

代码

class Solution {

int[] memory;

public int numWays(int n) {
memory = new int[n+1];
return help(n);
}

public int help(int n) {
// 递归结束的条件
if (n <= 1) {
return 1;
}

// 判断是否计算过了
if (memory
 != 0) {
return memory
;
}

// 没有在 memory 中找到就计算一下,然后在记录到 memory 中
int i = help(n - 1) + help(n - 2);
i %= 1000000007;
memory
 = i;

return memory
;
}
}

复杂度分析

  • 时间复杂度:O(N)
  • 空间复杂度:O(N)

思路2(迭代 / 动态规划)

  • 同样,根据斐波那契数列定义,可以发现第
    n
    个的值为前两个值之和,因此我们可以从第一个开始计算,循环计算到
    n
    就得到了结果,空间上仅仅占两个变量的空间,为 O(1) ,代码如下:

代码

class Solution {
public int numWays(int n) {
if (n <= 1) {
return 1;
}

int a = 1;
int b = 2;

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

return b;
}
}

复杂度分析

  • 时间复杂度:O(N)
  • 空间复杂度:O(1)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: