LeetCode:爬楼梯

1、问题描述

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

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

示例 1:

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

示例 2:

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

提示:

  • 1 <= n <= 45

2、解题思路

解法 1:递归(暴力解法)

思路
  • 递推关系f(n) = f(n-1) + f(n-2),即爬到第 n 阶的方法数等于爬到 n-1 阶(最后一步迈 1 阶)和 n-2 阶(最后一步迈 2 阶)的方法数之和。

  • 边界条件

    • f(1) = 1(只有 1 阶,1 种方法)

    • f(2) = 2(可以 1+1 或直接迈 2 阶)

 public int climbStairs(int n) {
        //递归算法--->时间复杂度为O(N*N)
        p(n) = P(n-1) + p(n-2)
        if(n == 1){
            return 1;
        }
        if(n == 2){
            return 2;//要么一阶一阶爬,要么直接两阶
        } 
        return climbStairs(n-1) + climbStairs(n-2);
}
复杂度分析
  • 时间复杂度O(2^n),因为递归树呈指数级增长,存在大量重复计算。

  • 空间复杂度O(n),递归栈深度最大为 n

缺点
  • 重复计算:比如计算 f(5) 时,f(3) 会被计算多次,效率极低。

解法 2:递归 + 记忆化(HashMap 存储)

思路
  • 优化递归:使用 HashMap 存储已经计算过的 f(n),避免重复计算。

  • 步骤

    1. 检查 HashMap 是否已经存储了 f(n),如果有,直接返回。

    2. 如果没有,计算 f(n) = f(n-1) + f(n-2),并存入 HashMap

    private Map<Integer,Integer> storeMap = new HashMap<>();
    public int climbStairs(int n) {
        //使用hashmap存储计算好的第i个方法,时间复杂度为O(N),空间复杂度为O(N)
        if(n==1) return 1;
        if(n==2) return 2;
        if(storeMap.get(n) != null){
            return storeMap.get(n);
        }
        else{
            int result = climbStairs(n-1) + climbStairs(n-2);
            storeMap.put(n,result);
            return result;
        }
}
复杂度分析
  • 时间复杂度O(n),每个 f(n) 只计算一次。

  • 空间复杂度O(n),存储 HashMap 和递归栈。

优点
  • 避免重复计算,大幅提升效率。

解法 3:动态规划(数组存储)

思路
  • 递推关系dp[i] = dp[i-1] + dp[i-2],其中 dp[i] 表示爬到第 i 阶的方法数。

  • 边界条件

    • dp[0] = 1(0 阶可以视为 1 种方法,方便计算)

    • dp[1] = 1(1 阶只有 1 种方法)

    • dp[2] = 2(2 阶有 2 种方法)

public int climbStairs(int n) {
      
        //动态规划--->时间复杂度为O(N),空间复杂度为O(N)
        if(n<=1) return 1; // 处理0和1的情况,否则后面会出现数组越界问题。
        int[] dp = new int[n];
        dp[0] = 1;  //表示一个台阶,1种解法
        dp[1] = 2;  //表示两个台阶,有一步一步和直接两步的2种解法
        for(int i=2;i<n;i++){
            dp[i] = dp[i-1] + dp[i-2];
        } 
        return dp[n-1];
}
复杂度分析
  • 时间复杂度O(n),只需遍历一次。

  • 空间复杂度O(n),需要 dp 数组存储中间结果。

优点
  • 避免递归栈溢出,适合较大的 n

解法 4:动态规划(优化空间,仅存储前两个状态)

思路
  • 优化空间:由于 dp[i] 只依赖 dp[i-1] 和 dp[i-2],可以用变量代替数组。

  • 变量定义

    • prev1 表示 dp[i-1]

    • prev2 表示 dp[i-2]

    • current 表示 dp[i]

public int climbStairs(int n) {
        //动态规划,不适用数组存储,因为题目要求只需要返回第n阶有多少种方式,即返回最后一次的即可
        //时间复杂度为O(N),空间复杂度为O(1)
         int first = 0, second = 0;
         int result = 1;
         for(int i=1;i<=n;i++){
             first = second;
             second = result;
             result = first + second;
            
         }
         return result;

    }
复杂度分析
  • 时间复杂度O(n),遍历一次。

  • 空间复杂度O(1),仅用 3 个变量。

优点
  • 空间最优,适用于 n 非常大的情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值