前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LeetCode题解—青蛙跳台阶

LeetCode题解—青蛙跳台阶

作者头像
码上积木
发布2021-04-16 10:28:33
2.3K0
发布2021-04-16 10:28:33
举报
文章被收录于专栏:码上积木
前言

今天聊个经典题目:青蛙跳台阶问题

题目

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

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

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

示例 2:输入:n = 7 输出:21

题解

假设 n 级的台阶共有f(n)种跳法,那么共有两种情况可以跳到第n级:

  • 1、在n-1级台阶地方,跳一步到n级台阶
  • 2、在n-2级台阶地方,跳两步到n级台阶

所以得出, f(n) = f(n-1) + f(n-2)。

所以这题其实就是一道斐波那契数列。

斐波那契数列我们就熟悉了啊,之前专门写过一篇。

我们可以得出第一种解法:递归

解法1

代码语言:javascript
复制
public int numWays(int n) {
        if(n==0)return 1;
        if(n<3)return n;
        int first=numWays(n-1) % 1000000007;
        int second=numWays(n-2)% 1000000007;
        return (first+second)% 1000000007;
    }

还是老问题,这种递归会有大量重复计算。

比如f(5)=f(4)+f(3),f(4)=f(3)+f(2),f(3)计算了两次。

所以我们将它优化下,对于已经计算过的数值存储起来。

解法2

记忆化递归方法,用数组memo存储已经计算过的数值。

代码语言:javascript
复制
class Solution {
    private int[] memo;

    public int numWays(int n) {
        memo = new int[n + 1];
        Arrays.fill(memo, -1);
        return jump(n);
    }

    private int jump(int n) {
        if (memo[n] != -1) {
            return memo[n];
        }
        if (n == 1 || n == 0) {
            return 1;
        }
        memo[n] = (jump(n - 1) + jump(n - 2)) % 1000000007;
        return memo[n];
    }
}

时间复杂度

O(n)

空间复杂度

O(n)

解法3

有没有更好的解法呢?可以发现在这个问题中,每次计算得出的结果又可以被下一个台阶所利用,并得出新的结果。

比如f(5)要用到f(4)和f(3)的结果,f(4)又可以被f(6)所利用。

这种大问题可以被解析成小问题,并且小问题的结果可以被重复调用的情况,就可以用到 动态规划算法

还是贯彻f(n) = f(n-1) + f(n-2)的公式,用一个数组进行存储结果,可以得出初步的动态规划解法:

代码语言:javascript
复制
    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];
    }

时间复杂度

O(n)

空间复杂度

O(n)

解法4

还能不能优化呢?

其实这个数组可以不用,使用两个变量存储结果,每次存储新的结果就可以,因为每次都只需要上两个结果。

代码语言:javascript
复制
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;
    }

用pre和cur两个变量代替了之前的数组dp,每次计算完下一个值之后,也就是tmp=pre+cur。

再次对pre和cur重新赋值,如此反复,最终完成计算。

这种解法的空间复杂度就能优化为O(1)。

参考

https://leetcode-cn.com/problems/qing-wa-tiao-tai-jie-wen-ti-lcof/

感谢大家的阅读,有一起学习的小伙伴可以关注下公众号—码上积木❤️ 每日一个知识点,建立完整体系架构。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码上积木 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目
  • 题解
  • 解法1
  • 解法2
    • 时间复杂度
      • 空间复杂度
      • 解法3
        • 时间复杂度
          • 空间复杂度
          • 解法4
          • 参考
          相关产品与服务
          对象存储
          对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档