题目描述

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

image-20261001225023159

题意分析

青蛙从第 0 级出发,每次只能向上跳 1 级或 2 级,求恰好到达第 n 级的不同跳法数量。跳跃的先后顺序不同就算不同方案,不是只统计两种步长各用了多少次。

n = 0 时,不进行任何跳跃也算一种完成方式。按本题的返回要求,方案数需要对 1000000007 取模;返回的是方案数量,不是最少跳跃次数。

解法:滚动变量动态规划

核心思路

[!blue]

令 ways[i] 表示恰好到达第 i 级的跳法数量。对于 i >= 2,最后一跳只有两种情况:从第 i - 1 级跳一级,或从第 i - 2 级跳两级。任意到达对应前一位置的方案,都能追加这最后一跳得到一个完整方案;两类最后一步不同,不会重复,而且覆盖全部可能,所以 ways[i] = ways[i - 1] + ways[i - 2]。

初值为 ways[0] = 1、ways[1] = 1。零级的一种空方案,使“直接跳两级”也能由递推计入;如果把它当成零种,会漏掉这类从起点直接出发的方案。

每项只依赖相邻的前两项,保存两个变量即可。执行了 i 轮更新后,a 表示 ways[i],b 表示 ways[i + 1]。先求两者之和得到再下一项,再把旧 b 移到 a、把新值移到 b,就保持了下一轮需要的状态。执行 n 轮后返回 a,它恰好对应第 n 级。

这里保存的都是方案数的余数。加法满足先取模再相加与最后取模等价,所以每轮都取模不会改变最终答案。两个状态都小于模数,它们相加也仍在 32 位有符号整数范围内;无需先算出可能很大的完整方案数。

解题步骤

  1. 设模数为 1000000007,初始化 a = 1、b = 1,分别对应零级和一级的方案数。
  2. 共执行 n 轮,每轮先计算下一项 (a + b) % MOD。
  3. 将旧 b 赋给 a,再把刚算出的下一项赋给 b;Go 的并行赋值会先计算右侧,因此同样保留了两个旧值。
  4. 返回 a。零级时不进入循环,直接返回空方案数量 1。

代码实现

class Solution {
    private static final int MOD = 1000000007;

    public int numWays(int n) {
        // 零级台阶也有一种完成方式,初值与普通斐波那契不同。
        int a = 1;
        int b = 1;

        for (int i = 0; i < n; i++) {
            int sum = (a + b) % MOD;

            a = b;
            b = sum;
        }

        return a;
    }
}
func numWays(n int) int {
    const mod = 1000000007
    // 零级台阶也有一种完成方式,初值与普通斐波那契不同。
    a, b := 1, 1
    for i := 0; i < n; i++ {
        a, b = b, (a+b)%mod
    }
    return a
}

复杂度分析

  • 时间复杂度:$O(n)$,执行 n 次常数时间的滚动更新。
  • 空间复杂度:$O(1)$,只保存相邻两项及一次加法结果。

关键点总结

[!green]

  • 按最后一跳的步长分类,得到不重复、不遗漏的计数递推。
  • 零级不是零种方案,空方案是递推的必要边界。
  • 明确第 i 轮之后两个变量分别代表哪两项,才能确定循环次数和返回值。
  • 每轮对加法结果取模,既保持答案正确,也控制中间数值大小。

易错点总结

[!yellow]

  • 沿用普通斐波那契的零初值,会把本题方案数整体算错;这里两个初值均为 1。
  • 忽略跳跃顺序,把相同步长数量视为同一方案,会漏掉不同的排列。
  • 只在最后取模,无法修复递推中早已发生的整数溢出。
  • Java 未先算新值就覆盖旧变量,会错误地重复使用同一个状态。
  • 本实现更新 n 轮后返回 a,不能混用其他初始化方式对应的轮数和返回位置。

相似题目

题目 难度 关联与区别
746. 使用最小花费爬楼梯 简单 移动步数仍为1或2,原题最小化费用,本题统计不同走法。
1137. 第 N 个泰波那契数 简单 同样根据有限个前项滚动递推,原题依赖前三项,本题依赖前两项。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2026/45943886
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!