(LeetCode-Hot100)70. 爬楼梯

问题简介

70. 爬楼梯 - LeetCode

题目描述

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 12 个台阶。你有多少种不同的方法可以爬到楼顶呢?


❌|✅|💡|📌 示例说明

示例 1:

复制代码
输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶

示例 2:

复制代码
输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶

❌|✅|💡|📌 解题思路

思路一:动态规划(推荐)

这是一个经典的斐波那契数列问题。

步骤分析:

  1. 定义状态 :设 dp[i] 表示爬到第 i 阶的方法数。
  2. 状态转移方程
    • 要到达第 i 阶,可以从第 i-1 阶走 1 步,或从第 i-2 阶走 2 步。
    • 所以:dp[i] = dp[i-1] + dp[i-2]
  3. 初始条件
    • dp[0] = 1(站在地面也算一种方式)
    • dp[1] = 1
  4. 目标 :求 dp[n]

💡 注意:此题本质是斐波那契数列的第 n+1 项。


思路二:空间优化的动态规划

由于 dp[i] 只依赖前两个值,可以用两个变量代替整个数组,将空间复杂度从 O(n) 降到 O(1)。


思路三:递归 + 记忆化(备忘录)

直接递归会超时(指数时间),但加上记忆化(缓存已计算结果)可优化为 O(n) 时间。


思路四:数学公式(Binet 公式)

斐波那契数列有闭式解:
F ( n ) = f r a c p h i n − p s i n s q r t 5 , q u a d t e x t 其中 p h i = f r a c 1 + s q r t 5 2 , p s i = f r a c 1 − s q r t 5 2 F(n) = \\frac{\\phi^n - \\psi^n}{\\sqrt{5}}, \\quad \\text{其中} \\ \\phi = \\frac{1+\\sqrt{5}}{2}, \\ \\psi = \\frac{1-\\sqrt{5}}{2} F(n)=fracphin−psinsqrt5,quadtext其中phi=frac1+sqrt52,psi=frac1−sqrt52

但由于浮点精度问题,一般不推荐用于编程题。


❌|✅|💡|📌 代码实现

java 复制代码
class Solution {
    // 方法一:动态规划(数组)
    public int climbStairs1(int n) {
        if (n <= 1) return 1;
        int[] dp = new int[n + 1];
        dp[0] = 1;
        dp[1] = 1;
        for (int i = 2; i <= n; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];
    }

    // 方法二:空间优化(推荐)
    public int climbStairs(int n) {
        if (n <= 1) return 1;
        int prev2 = 1; // dp[0]
        int prev1 = 1; // dp[1]
        int curr = 0;
        for (int i = 2; i <= n; i++) {
            curr = prev1 + prev2;
            prev2 = prev1;
            prev1 = curr;
        }
        return curr;
    }

    // 方法三:记忆化递归
    private Map<Integer, Integer> memo = new HashMap<>();
    public int climbStairs3(int n) {
        if (n <= 1) return 1;
        if (memo.containsKey(n)) {
            return memo.get(n);
        }
        int res = climbStairs3(n - 1) + climbStairs3(n - 2);
        memo.put(n, res);
        return res;
    }
}
Go 复制代码
func climbStairs(n int) int {
    if n <= 1 {
        return 1
    }
    prev2 := 1 // dp[0]
    prev1 := 1 // dp[1]
    curr := 0
    for i := 2; i <= n; i++ {
        curr = prev1 + prev2
        prev2 = prev1
        prev1 = curr
    }
    return curr
}

// 可选:带记忆化的递归版本
func climbStairsMemo(n int) int {
    memo := make(map[int]int)
    var dfs func(int) int
    dfs = func(i int) int {
        if i <= 1 {
            return 1
        }
        if val, ok := memo[i]; ok {
            return val
        }
        res := dfs(i-1) + dfs(i-2)
        memo[i] = res
        return res
    }
    return dfs(n)
}

❌|✅|💡|📌 示例演示

n = 5 为例:

阶数 i dp[i] 计算过程
0 初始 1
1 初始 1
2 dp[1] + dp[0] = 1+1 2
3 dp[2] + dp[1] = 2+1 3
4 dp[3] + dp[2] = 3+2 5
5 dp[4] + dp[3] = 5+3 8

✅ 输出:8

所有路径(共8种):

  1. 1+1+1+1+1
  2. 1+1+1+2
  3. 1+1+2+1
  4. 1+2+1+1
  5. 2+1+1+1
  6. 1+2+2
  7. 2+1+2
  8. 2+2+1

❌|✅|💡|📌 答案有效性证明

  • 数学归纳法
    • 基础:n=1 时,1 种;n=2 时,2 种,成立。
    • 假设对所有 k < n 成立,则 n 阶只能由 n-1(走1步)或 n-2(走2步)到达。
    • f(n) = f(n-1) + f(n-2),符合斐波那契递推。
  • 因此,动态规划解法正确。

❌|✅|💡|📌 复杂度分析

方法 时间复杂度 空间复杂度 说明
动态规划(数组) O(n) O(n) 存储全部 dp 值
空间优化 DP ✅ O(n) ✅ O(1) 最优解
记忆化递归 O(n) O(n) 递归栈 + 哈希表
纯递归(无记忆) O(2ⁿ) O(n) ❌ 超时,不推荐
数学公式 O(1) O(1) ⚠️ 浮点误差风险,不实用

❌|✅|💡|📌 问题总结

  • 本题是动态规划入门经典题 ,核心在于识别出状态转移关系
  • 实质是求斐波那契数列第 n+1 项
  • 推荐使用空间优化的迭代解法,简洁高效。
  • 此类"一步/两步"问题广泛出现在路径计数、硬币组合等场景中,掌握其思想可举一反三。
  • 💡 关键洞察:当前状态仅依赖前两个状态 → 可压缩空间。

github地址: https://github.com/swf2020/LeetCode-Hot100-Solutions

相关推荐
前路不黑暗@1 小时前
Java项目:Java脚手架项目的阿里云短信服务集成(十六)
android·java·spring boot·学习·spring cloud·阿里云·maven
海南java第二人1 小时前
Flink运行时组件深度解析:Java工程师的架构设计与实战指南
java·大数据·flink
WJX_KOI1 小时前
保姆级教程:Apache Flink CDC(standalone 模式)部署 MySQL CDC、PostgreSQL CDC 及使用方法
java·大数据·mysql·postgresql·flink
不想看见4042 小时前
Climbing Stairs 基本动态规划:一维--力扣101算法题解笔记
算法·leetcode·动态规划
陈天伟教授2 小时前
人工智能应用- 推荐算法:05.推荐算法的社会争议
算法·机器学习·推荐算法
追随者永远是胜利者2 小时前
(LeetCode-Hot100)49. 字母异位词分组
java·算法·leetcode·职场和发展·go
apcipot_rain2 小时前
原神“十盒半价”问题的兹白式建模分析
python·数学·算法·函数·数据科学·原神·数列
吴声子夜歌2 小时前
RxJava——Flowable与背压
android·java·rxjava
小刘的大模型笔记2 小时前
PPO与DPO:大模型对齐的两大核心算法,差异与选型全解析
算法