LeetCode 70 爬楼梯

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

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

看到这题, 脑子里想到的就是动态规划, 什么是动态规划, 一言以蔽之就是, 记住你已经做过的计算, 在已经计算过的基础上叠加, 避免重复的计算.

首先, 不妨将阶梯数想象成一个全是1组成的数组, 比如8级阶梯, 就是:
[1, 1, 1, 1, 1, 1, 1, 1]
那么不同的爬楼梯方案就类似于:
[2, 1, 1, 1, 1, 1, 1], [1, 2, 1, 1, 1, 1, 1], [2, 2, 1, 1, 1, 1] ......
当只有一个阶梯走跨两步时, 就可能出现7中情况, 即:
[2, 1, 1, 1, 1, 1, 1], [1, 2, 1, 1, 1, 1, 1], [1, 1, 2, 1, 1, 1, 1], [1, 1, 1, 2, 1, 1, 1] ......
而当两个阶梯走跨两步时, 可能出现如下情况:
[2, 2, 1, 1, 1, 1], [2, 1, 2, 1, 1, 1], [2, 1, 1, 2, 1, 1], [2, 1, 1, 1, 2, 1], [2, 1, 1 ,1, 1, 2],
[1, 2, 2, 1, 1, 1], [1, 2, 1, 2, 1, 1], [1, 2, 1, 1, 2, 1], [1, 2, 1, 1, 1, 2],
[1, 1, 2, 2, 1, 1], [1, 1, 2, 1, 2, 1], [1, 1, 2, 1, 1, 2]
......
注意到这里两次跨两步的情况都是在一次跨两步的基础下得的出来的, 具体就是在一次跨两步的那个两步之后选择跨两步的位置, 这样避免出现重复的跨步情况, 又能完整遍历出结果, 基于这个方案, 我写出了第一种算法

  func climbStairs(_ n: Int) -> Int {
        if n > 0 {
            var count = 1
            for i in 1..<n {

                count += self.climbStairs(n - i - 1)
            }
            return count
        } else {
             
            return 1
        }  
  }

每个台阶总数全为1, 是一种情况, 然后在这个全为一的数组中凑出一个2,
得到多种情况, 在每种情况下, 将凑出的那个2去掉, 使2之后剩下的1成为一个新的值, 向下递归, 直到n = 0, 这个时候我们知道, 只有1种情况

但是很不幸这种方式超时了, 因为里面还是包含了太多的重复计算
以数字8为例:
当我们传入一个8, 他将递归计算值为6, 5, 4, 3, 2, 1, 0的结果
而计算6, 则将递归计算4, 3, 2, 1, 0的结果
计算5将计算3, 2, 1, 0的结果
...
可以看到, 0的结果, 1的结果, 2的结果将被重复计算多次, 而这些计算是不需要的
于是我重新观察这种方案, 当n = 0时, 可以直接得出1, 当n = 1时可以直接得出1, 当n = 2时, 可以视为 1 + (n = 0), 以此类推:
n = 0: 1
n = 1: 1
n = 2: 1 + (n = 0)
n = 3: 1 + (n = 1) + (n = 0)
n = 4: 1 + (n = 2) + (n = 1) + (n = 0)
n = 5: 1 + (n = 3) + (n = 2) + (n = 1) + (n = 0)
...
可以观察到:
n = 4: (n = 3) + (n = 2)
n = 5: (n = 4) + (n = 3)
于是可以通过累加法, 从n = 2开始
记下n = 0 和 n = 1
n = 2 就等于 (n = 0) + (n = 1)
记下n = 1 和 n = 2
n = 3 就等于 (n = 2) + (n = 1)
记下n = 2 和 n = 3
n = 4 就等于 (n = 3) + (n = 2)
...
最终得出答案

    func climbStairs(_ n: Int) -> Int {
        
        if n > 1 {
            var lastTwo = 1
            var addCount = 1
            for index in 2...n {
                let tLast = lastTwo
                lastTwo = addCount
                addCount += tLast
            }
            return addCount
        } else {
            return 1
        }   
    }

提交通过

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 写在前沿:本文代码均使用C语言编写 Description:假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可...
    小黄大大阅读 295评论 0 0
  • 原题地址:https://leetcode-cn.com/problems/climbing-stairs/ 题目...
    IgorNi阅读 488评论 0 0
  • 题目: 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以...
    SenwinFeng阅读 627评论 0 0
  • 问题描述 你正在爬楼梯。需要 n 步你才能到达顶部。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方式可以爬...
    Dy1an阅读 497评论 0 0
  • 学生宁*运动员麦 私设严重 麦克沃伊是个非常爽朗的大男孩,抛去了他的运动明星身份,私底下也是一个非常爱闹爱疯的主,...
    玘子阅读 143评论 0 0