You are climbing a stair case. It takes n steps to reach to the top.

Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

Note: Given n will be a positive integer.

Example 1:

  1. Input: 2
  2. Output: 2
  3. Explanation: There are two ways to climb to the top.
  4. 1. 1 step + 1 step
  5. 2. 2 steps

Example 2:

  1. Input: 3
  2. Output: 3
  3. Explanation: There are three ways to climb to the top.
  4. 1. 1 step + 1 step + 1 step
  5. 2. 1 step + 2 steps
  6. 3. 2 steps + 1 step

这篇博客最开始名字叫做爬梯子问题,总是有童鞋向博主反映移动端打不开这篇博客,博主觉得非常奇怪,自己也试了一下,果然打不开。心想着是不是这个博客本身有问题,于是想再开一个相同的帖子,结果还是打不开,真是见了鬼了。于是博主换了个名字,结果居然打开了?!进经过排查后发现,原来是“爬梯子”这三个字是敏感词,放到标题里面,博客就被屏蔽了,我也真是醉了,完全是躺枪好么,无奈之下,只好改名为爬楼梯问题了 -。-|||。

这个爬梯子问题最开始看的时候没搞懂是让干啥的,后来看了别人的分析后,才知道实际上跟斐波那契数列非常相似,假设梯子有n层,那么如何爬到第n层呢,因为每次只能爬1或2步,那么爬到第n层的方法要么是从第 n-1 层一步上来的,要不就是从 n-2 层2步上来的,所以递推公式非常容易的就得出了:dp[n] = dp[n-1] + dp[n-2]。 由于斐波那契额数列的求解可以用递归,所以博主最先尝试了递归,拿到 OJ 上运行,显示 Time Limit Exceeded,就是说运行时间超了,因为递归计算了很多分支,效率很低,这里需要用动态规划 (Dynamic Programming) 来提高效率,代码如下:

C++ 解法一:

  1. class Solution {
  2. public:
  3. int climbStairs(int n) {
  4. if (n <= ) return ;
  5. vector<int> dp(n);
  6. dp[] = ; dp[] = ;
  7. for (int i = ; i < n; ++i) {
  8. dp[i] = dp[i - ] + dp[i - ];
  9. }
  10. return dp.back();
  11. }
  12. };

Java 解法一:

  1. public class Solution {
  2. public int climbStairs(int n) {
  3. if (n <= 1) return 1;
  4. int[] dp = new int[n];
  5. dp[0] = 1; dp[1] = 2;
  6. for (int i = 2; i < n; ++i) {
  7. dp[i] = dp[i - 1] + dp[i - 2];
  8. }
  9. return dp[n - 1];
  10. }
  11. }

我们可以对空间进行进一步优化,只用两个整型变量a和b来存储过程值,首先将 a+b 的值赋给b,然后a赋值为原来的b,所以应该赋值为 b-a 即可。这样就模拟了上面累加的过程,而不用存储所有的值,参见代码如下:

C++ 解法二:

  1. class Solution {
  2. public:
  3. int climbStairs(int n) {
  4. int a = , b = ;
  5. while (n--) {
  6. b += a;
  7. a = b - a;
  8. }
  9. return a;
  10. }
  11. };

Java 解法二:

  1. public class Solution {
  2. public int climbStairs(int n) {
  3. int a = 1, b = 1;
  4. while (n-- > 0) {
  5. b += a;
  6. a = b - a;
  7. }
  8. return a;
  9. }
  10. }
虽然前面说过递归的写法会超时,但是只要加上记忆数组,那就不一样了,因为记忆数组可以保存计算过的结果,这样就不会存在重复计算了,大大的提高了运行效率,其实递归加记忆数组跟迭代的 DP 形式基本是大同小异的,参见代码如下:

C++ 解法三:

  1. class Solution {
  2. public:
  3. int climbStairs(int n) {
  4. vector<int> memo(n + );
  5. return helper(n, memo);
  6. }
  7. int helper(int n, vector<int>& memo) {
  8. if (n <= ) return ;
  9. if (memo[n] > ) return memo[n];
  10. return memo[n] = helper(n - , memo) + helper(n - , memo);
  11. }
  12. };

Java 解法三:

  1. public class Solution {
  2. public int climbStairs(int n) {
  3. int[] memo = new int[n + 1];
  4. return helper(n, memo);
  5. }
  6. public int helper(int n, int[] memo) {
  7. if (n <= 1) return 1;
  8. if (memo[n] > 0) return memo[n];
  9. return memo[n] = helper(n - 1, memo) + helper(n - 2, memo);
  10. }
  11. }
论坛上还有一种分治法 Divide and Conquer 的解法,用的是递归形式,可以通过,但是博主没有十分理解,希望各位看官大神可以跟博主讲一讲~

C++ 解法四:

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

Java 解法四:

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

最后来看一种叼炸天的方法,其实斐波那契数列是可以求出通项公式的,推理的过程请参见 知乎上的这个贴子,那么有了通项公式后,直接在常数级的时间复杂度范围内就可以求出结果了,参见代码如下:

C++ 解法五:

  1. class Solution {
  2. public:
  3. int climbStairs(int n) {
  4. double root5 = sqrt();
  5. return ( / root5) * (pow(( + root5) / , n + ) - pow(( - root5) / , n + ));
  6. }
  7. };

Java 解法五:

  1. public class Solution {
  2. public int climbStairs(int n) {
  3. double root5 = Math.sqrt(5);
  4. double res = (1 / root5) * (Math.pow((1 + root5) / 2, n + 1) - Math.pow((1 - root5) / 2, n + 1));
  5. return (int)res;
  6. }
  7. }

Github 同步地址:

https://github.com/grandyang/leetcode/issues/70

类似题目:

Min Cost Climbing Stairs

Fibonacci Number

参考资料:

https://leetcode.com/problems/climbing-stairs/

https://leetcode.com/problems/climbing-stairs/discuss/25345/Easy-solutions-for-suggestions.

https://leetcode.com/problems/climbing-stairs/discuss/25296/3-4-short-lines-in-every-language

https://leetcode.com/problems/climbing-stairs/discuss/25608/My-divide-and-conquer-way-to-solve-this-problem(Java)

https://leetcode.com/problems/climbing-stairs/discuss/25436/Using-the-Fibonacci-formular-to-get-the-answer-directly

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 70. Climbing Stairs 爬楼梯问题的更多相关文章

  1. [LeetCode] 70. Climbing Stairs 爬楼梯

    You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb ...

  2. LeetCode 70. Climbing Stairs爬楼梯 (C++)

    题目: You are climbing a stair case. It takes n steps to reach to the top. Each time you can either cl ...

  3. [leetcode]70. Climbing Stairs爬楼梯

    You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb ...

  4. Leetcode 70. Climbing Stairs 爬楼梯 (递归,记忆化,动态规划)

    题目描述 要爬N阶楼梯,每次你可以走一阶或者两阶,问到N阶有多少种走法 测试样例 Input: 2 Output: 2 Explanation: 到第二阶有2种走法 1. 1 步 + 1 步 2. 2 ...

  5. 70. Climbing Stairs爬楼梯

    网址:https://leetcode.com/problems/climbing-stairs/ 其实就是斐波那契数列,没什么好说的. 注意使用3个变量,而不是数组,可以节约空间. class So ...

  6. Leetcode#70. Climbing Stairs(爬楼梯)

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

  7. 42. leetcode 70. Climbing Stairs

    70. Climbing Stairs You are climbing a stair case. It takes n steps to reach to the top. Each time y ...

  8. LN : leetcode 70 Climbing Stairs

    lc 70 Climbing Stairs 70 Climbing Stairs You are climbing a stair case. It takes n steps to reach to ...

  9. leetCode 70.Climbing Stairs (爬楼梯) 解题思路和方法

    Climbing Stairs  You are climbing a stair case. It takes n steps to reach to the top. Each time you ...

随机推荐

  1. app版本升级的测试点

    移动端版本更新升级是一个比较重要的功能点,主要分为强制更新和非强制更新. 1.强制更新需要测试的点有: 1)强制升级是否可以升级成功 从老版本的包升级到新版版的包是否可以升级成功. 2)升级后的数据是 ...

  2. 【05】Nginx:TCP / 正向 / 反向代理 / 负载均衡

    写在前面的话 在我们日常的工作中,不可能所有的服务都是简单的 HTML 静态网页,nginx 作为轻量级的 WEB 服务器,其实我们将它用于更多的地方还是作为我们网站的入口.不管你是后端接口,还是前端 ...

  3. C# 人民币大写金额转换

    /// <summary>       /// 转换人民币大小金额       /// </summary>       /// <param name="nu ...

  4. vue 上传进度显示

    参考资料: https://ask.csdn.net/questions/767017 https://www.cnblogs.com/best-fyx/p/11363506.html 我使用的是el ...

  5. C#写日志工具类

    代码: using System; using System.Collections.Generic; using System.IO; using System.Linq; using System ...

  6. 超时空英雄传说2复仇魔神完全攻略&秘技

    ╓─╥───────────────────────────────────────────────────╥─╖ ║ ║ 超 時 空 英 雄 傳 說 2 ║ ║ ║ ║ --復 仇 魔 神-- ║ ...

  7. mvc 返回json格式时间格式化

    protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEnco ...

  8. IOS疯狂基础之观察者模式

    转自:http://blog.csdn.net/wudizhukk/article/details/8981535 一.KVO Key-Value Observing,它提供一种机制,当指定的对象的属 ...

  9. 如何在一个ubuntu系统上搭建SVN版本控制工具

    有话说,由于公司项目部署需要,将Windows工程迁移到Linux,通过调查确定使用Ubuntu的Linux操作系统.那么如何快速搭建和Windows一样快捷方便的开发环境就很重要了.本文讲述如何在一 ...

  10. tensorflow模型量化实例

    1,概述 模型量化应该是现在最容易实现的模型压缩技术,而且也基本上是在移动端部署的模型的毕竟之路.模型量化基本可以分为两种:post training quantizated和quantization ...