来源

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/climbing-stairs/

描述

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。

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

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

题解

递归

  1. class Solution {
  2. public int climbStairs(int n) {
  3. if (1 == n) return 1;
  4. if (2 == n) return 2;
  5. return climbStairs(n - 1) + climbStairs(n - 2);
  6. }
  7. }

此方法,超时!
复杂度分析

  • 时间复杂度:70. 爬楼梯(Climbing Stairs) - 图1,此种计算方式会出现大量冗余;
  • 空间复杂度:70. 爬楼梯(Climbing Stairs) - 图2,递归树的深度可以达到n;

    动态规划

    这个问题可以被分解为一些包含最优子结构的子问题,即它的最优解可以从其子问题的最优解来有效地构建,我们可以使用动态规划来解决这一问题。

70. 爬楼梯(Climbing Stairs) - 图3阶可以由以下两种方法得到:

  • 在第70. 爬楼梯(Climbing Stairs) - 图4阶后向上爬1阶;
  • 在第70. 爬楼梯(Climbing Stairs) - 图5阶后向上爬2阶;

    所以到达第70. 爬楼梯(Climbing Stairs) - 图6阶的方法总数就是到第70. 爬楼梯(Climbing Stairs) - 图7阶和第70. 爬楼梯(Climbing Stairs) - 图8阶的方法之和,70. 爬楼梯(Climbing Stairs) - 图9

    class Solution {
      public int climbStairs(int n) {
          if (1 == n) 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 - 1] + dp[i - 2];
          }
    
          return dp[n];
      }
    }
    

    复杂度分析

  • 时间复杂度:70. 爬楼梯(Climbing Stairs) - 图10,单循环到70. 爬楼梯(Climbing Stairs) - 图11

  • 空间复杂度:70. 爬楼梯(Climbing Stairs) - 图12,dp数组用了70. 爬楼梯(Climbing Stairs) - 图13的空间;

    斐波那切数列

    将动态规划方法中的空间复杂度优化到70. 爬楼梯(Climbing Stairs) - 图14

    class Solution {
      public int climbStairs(int n) {
          if (1 == n) return 1;
    
          int first = 1;
          int second = 2;
          for (int i = 3; i <= n; i++) {
              int third = first + second;
              first = second;
              second = third;
          }
    
          return second;
      }
    }
    

    复杂度分析

  • 时间复杂度:70. 爬楼梯(Climbing Stairs) - 图15,单循环到n,需要计算第n个斐波那契数;

  • 空间复杂度:70. 爬楼梯(Climbing Stairs) - 图16,使用常量级空间;