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:

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

Example 2:

Input: 3
Output: 3
Explanation: There are three ways to climb to the top.
1. 1 step + 1 step + 1 step
2. 1 step + 2 steps
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++ 解法一:

class Solution {
public:
int climbStairs(int n) {
if (n <= ) return ;
vector<int> dp(n);
dp[] = ; dp[] = ;
for (int i = ; i < n; ++i) {
dp[i] = dp[i - ] + dp[i - ];
}
return dp.back();
}
};

Java 解法一:

public class Solution {
public int climbStairs(int n) {
if (n <= 1) return 1;
int[] dp = new int[n];
dp[0] = 1; dp[1] = 2;
for (int i = 2; i < n; ++i) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n - 1];
}
}

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

C++ 解法二:

class Solution {
public:
int climbStairs(int n) {
int a = , b = ;
while (n--) {
b += a;
a = b - a;
}
return a;
}
};

Java 解法二:

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

C++ 解法三:

class Solution {
public:
int climbStairs(int n) {
vector<int> memo(n + );
return helper(n, memo);
}
int helper(int n, vector<int>& memo) {
if (n <= ) return ;
if (memo[n] > ) return memo[n];
return memo[n] = helper(n - , memo) + helper(n - , memo);
}
};

Java 解法三:

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

C++ 解法四:

class Solution {
public:
int climbStairs(int n) {
if(n <= ) return ;
return climbStairs(n / ) * climbStairs(n - n / ) + climbStairs(n / - ) * climbStairs(n - n / - );
}
};

Java 解法四:

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

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

C++ 解法五:

class Solution {
public:
int climbStairs(int n) {
double root5 = sqrt();
return ( / root5) * (pow(( + root5) / , n + ) - pow(( - root5) / , n + ));
}
};

Java 解法五:

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

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] Climbing Stairs 爬梯子问题的更多相关文章

  1. [LintCode] 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] climbing stairs 爬楼梯

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

  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] Min Cost Climbing Stairs 爬楼梯的最小损失

    On a staircase, the i-th step has some non-negative cost cost[i] assigned (0 indexed). Once you pay ...

  5. [LeetCode] 746. Min Cost Climbing Stairs 爬楼梯的最小损失

    On a staircase, the i-th step has some non-negative cost cost[i] assigned (0 indexed). Once you pay ...

  6. [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 ...

  7. Leetcode: climbing stairs

    July 28, 2015 Problem statement: You are climbing a stair case. It takes n steps to reach to the top ...

  8. [LeetCode] Climbing Stairs (Sequence DP)

    Climbing Stairs https://oj.leetcode.com/problems/climbing-stairs/ You are climbing a stair case. It ...

  9. [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 ...

随机推荐

  1. Java进击C#——应用开发之Linq和EF

    本章简言 上一章笔者对于WinForm开发过程用到的几个知识点做了讲解.笔者们可以以此为开端进行学习.而本章我们来讲一个跟ORM思想有关的知识点.在讲之前让我们想一下关于JAVA的hibernate知 ...

  2. javascript编程杂记

    1.数组深复制 var obj =[1,2,4]: var obj2 = obj.slice(0);

  3. C# webform上传图片并生成缩略图

    其实里面写的很乱,包括修改文件名什么的都没有仔细去写,主要是想记录下缩略图生成的几种方式 ,大家明白就好! void UpImgs() { if (FileUpload1.HasFile) { str ...

  4. 在DevExpress程序中使用TeeList控件以及节点查询的处理

    在很多情况下,我们需要通过树列表进行数据的展示,如一些有层次关系的数据,通过有层级的展示,能够使用户更加直观查看和管理相关的数据.在一般Winform开发的情况下,可以使用微软的TreeView控件, ...

  5. C#和Java中的Substring()

    吐槽-使用清理软件整理电脑要注意,不要清理的"太狠",不然你会受伤的! C#中的Substring() 示例 实现代码 using System;using System.Coll ...

  6. Delphi_03_Delphi_Object_Pascal_基本语法_01

    这次是一个基本语法的第一部分,包括变量.变量初始化.常量.运算符.字符串等内容. { 本程序演示 Delphi Pascal 的基本语法 1.变量及变量的初始化 2.常量 3.运算符 3. 4. } ...

  7. MAC远程连接服务器,不需要输入密码的配置方式

    cd ~/.ssh #没有则需要创建一个. mkdir ~/.ssh ssh-keygen -t rsa cd ~/.ssh scp id_rsa.pub root@IP地址:~/.ssh/id_rs ...

  8. 【JS基础】数组

    filter() 返回数组中的满足回调函数中指定的条件的元素. array1.filter(callbackfn[, thisArg]) 对数组array1中的每个元素调用回调函数callbackfn ...

  9. HTTP、HTTP2

      HTTP.HTTP2.0.SPDY.HTTPS 你应该知道的一些事 原文链接:http://www.alloyteam.com/2016/07/httphttp2-0spdyhttps-readi ...

  10. Oracle研究专题:Oracle系统安装与配置

    最近开始研究Oracle数据库,盖因公司的系统要么Oracle要么是mysql吧. 作为一个IT工作者,没有碰过Oracle是一件很匪夷所思得事情. 想到过去几年,乃至接触IT行业开始就只有玩过sql ...