LeetCode HOT 100 —— 70. 爬楼梯

219 阅读2分钟

Leetcode 70 爬楼梯

动态规划

题目描述

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

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

解题思路

当台阶数有 1 层时,有 1 种方法

当台阶数有 2 层时,有 2 种方法

当台阶数有 n 层时,有 ? 种方法


当我第一次爬上第 1 层台阶时,还有 n-1 层,有对应的 p 种方法

当我第一次爬上第 2 层台阶时,还有 n-2 层,有对应的 q 种方法

所以,当台阶数 >= 3时,就有 f(n-1) + f(n-2) 种方法

那么得出:

image.png

解题代码

第一种解法 递归

var climbStairs = function(n) {
  if(n === 1) return 1
  if(n === 2) return 2
  return climbStairs(n-1) + climbStairs(n-2)
}

时间复杂度:O(n2),LeetCode报超出时间限制。

第二种解法 递归优化

我们发现在递归过程中,比如现在有6层台阶,会求2遍 f(4),那么我们做个优化,把已经求过的f(n)放到map中。

image.png

var map = new Map()
var climbStairs = function(n) {
  if(n === 1) return 1
  if(n === 2) return 2
  if(map.has(n)) {
    map.get(n)
  } else {
    let res = climbStairs(n-1) + climbStairs(n-2)
    map.set(n, res)
    return res
  }
}

第三种解法 循环

之前是从 自顶向下 的推导 [ f(6) --> f(1)/f(2) ],这次我们从下向上推导,当求 f(3) 时,方法为 f(1) + f(2)种,当求 f(4) 时,方法为 f(2) + f(3) 种,也就是说 求 f(3) 用到了 f(2), 求 f(4) 用到刚才求出的 f(3) 和之前求出的 f(2),使用两个变量存 f(3) 和 f(2),每次循环求时迭代相加即可得出结果。

image.png

var climbStairs = function(n) {
  if(n === 1) return 1
  if(n === 2) return 2
  let res = 0
  let n1 = 1
  let n2 = 2
  for(let i = 3; i <= n; i++) {
    res = n1 + n2
    n1 = n2
    n2 = res
  }
  return res
}

相同题目:剑指 Offer 10- I. 斐波那契数列

题目描述:

image.png

这题和爬楼梯很相似,区别在于: 当 res 大于 1000000007 时,需要对结果取余。

/**
 * @param {number} n
 * @return {number}
 */
var fib = function(n) {
  const mod = 1000000007
  if(n < 2) return n
  let res = 0
  let n1 = 0
  let n2 = 1
  for(let i = 2; i <= n; i++) {
      res = (n1 + n2) % mod
      n1 = n2
      n2 = res
  }
  return res
};

图片来源:【【Leetcode算法500题】目前B站最完整的数据结构算法教程,包含所有刷题攻略!这还没人看,我不更了!-哔哩哔哩】 b23.tv/8jMxHQi