说明

算法:Climbing Stairs(爬楼梯)
LeetCode地址:https://leetcode.com/problems/climbing-stairs/

题目:
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.
3. 1 step + 1 step + 1 step
4. 1 step + 2 steps
5. 2 steps + 1 step

解题思路1 - 递归

爬楼梯直接思路递归法,登顶的最后一步有两种走法,也就是1步,后者2步。
所以可以得出公式f(n) = f(n-1) + f(n-2).

注意初始条件

  • f(1) = 1;
  • f(2) = 2;

复杂度分析,时间复杂度为2^n。
因为有重复的数据多次计算,比如f(3), 每个大于3的都要重新计算一次。
递归函数还有个弊端,需要担心函数调用栈溢出。

代码实现1

public class ClimbingStairs {public static int climbStairsWithRecursion(int n) {if (n == 1) {return 1;} else if (n == 2) {return 2;} else {return climbStairsWithRecursion(n - 1) + climbStairsWithRecursion(n - 2);}}
}

代码执行效率1

Runtime: 7107 ms, faster than 10.50% of Java online submissions for Climbing Stairs.
Memory Usage: 36.4 MB, less than 27.61% of Java online submissions for Climbing Stairs.

解题思路2 - 递归加缓存

递归执行效率太低真实原因,是因为数据重复计算,用数组memoryArray存储已经计算过得数据。

时间复杂度降低为O(n), 内存复杂度为O(n) .

代码实现2

public class ClimbingStairs {public static int climbStairsWithRecursionMemory(int n) {int[] memoryArray = new int[n + 1];return subClimbStairsWithRecursionMemory(n - 1, memoryArray) + subClimbStairsWithRecursionMemory(n - 2, memoryArray);}public static int subClimbStairsWithRecursionMemory(int n, int[] memoryArray) {if (n == 1) {return 1;} else if (n == 2) {return 2;} else {if (memoryArray[n] > 0) {return memoryArray[n];}memoryArray[n] = subClimbStairsWithRecursionMemory(n - 1, memoryArray) + subClimbStairsWithRecursionMemory(n - 2, memoryArray);return memoryArray[n];}}
}

代码执行效率 2

Runtime: 2 ms, faster than 90.23% of Java online submissions for Climbing Stairs.
Memory Usage: 36.5 MB, less than 6.57% of Java online submissions for Climbing Stairs.

解题思路3 - 动态规划

担心递归会有函数调用指针栈溢出风险,既然有子函数解决问题方案,动态规划呼之即出。
递推公式:f(n) = f(n-1) + f(n-2)

时间复杂度降低为O(n), 内存复杂度为O(n) .

代码实现3

public class ClimbingStairs {public static int climbStairsWithDynamic(int n) {if (n == 1) {return 1;}int dynamicArray[] = new int[n + 1];dynamicArray[1] = 1;dynamicArray[2] = 2;for (int i = 3; i <= n; i++) {dynamicArray[i] = dynamicArray[i - 1] + dynamicArray[i - 2];}return dynamicArray[n];}
}

解题思路4 - Fibonacci

内存占用太高,公式很熟悉Fibonacci, 直接用3个变量就好,first, second, third。
递推公式:f(n) = f(n-1) + f(n-2)

时间复杂度降低为O(n), 内存复杂度为O(1) .

代码实现4

public class ClimbingStairs {public static int climbStairsWithFibonacci(int n) {if (n == 1) {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;}
}

解题思路5 - Fibonacci优化变量

内存占用太高,公式很熟悉Fibonacci, 变量是否还可以不用临时变量third呢,是可以的。
递推公式:f(n) = f(n-1) + f(n-2)

时间复杂度降低为O(n), 内存复杂度为O(1) .

代码实现5

public class ClimbingStairs {public static int climbStairs(int n) {int a = 1, b = 1;while (--n > 0) {b = b + a;a = b - a;}return b;}
}

代码执行效率 5

Runtime: 1 ms, faster than 100.00% of Java online submissions for Climbing Stairs.
Memory Usage: 36.6 MB, less than 5.01% of Java online submissions for Climbing Stairs.

解题思路6 - Fibonacci Formula

实际上时间复杂度O(n)不是最优。用公式的时间复杂度为 : O(log(n)). 因为开根号方法pow用时间log(n) .

空间复杂度O(1).

代码实现6

public class ClimbingStairs {public static int climbStairsWithFibonacciFormula(int n) {double sqrt5= Math.sqrt(5);double fibn = Math.pow((1 + sqrt5) / 2, n + 1) - Math.pow((1 - sqrt5) / 2, n + 1);return (int)(fibn / sqrt5);}
}

代码执行效率 6

Runtime: 1 ms, faster than 100.00% of Java online submissions for Climbing Stairs.
Memory Usage: 36.4 MB, less than 24.93% of Java online submissions for Climbing Stairs.

测试

public static void main(String[] args) {int n1 = 2;System.out.println("input: " + n1 + " climbStairs: " + climbStairs(n1));int n2 = 3;System.out.println("input: " + n2 + " climbStairs: " + climbStairs(n2));int n3 = 20;System.out.println("input: " + n3 + " climbStairs: " + climbStairs(n3));System.out.println("input: " + n3 + " climbStairsWithRecursion: " + climbStairsWithRecursion(n3));System.out.println("input: " + n3 + " climbStairsWithRecursionMemory: " + climbStairsWithRecursionMemory(n3));System.out.println("input: " + n3 + " climbStairsWithDynamic: " + climbStairsWithDynamic(n3));System.out.println("input: " + n3 + " climbStairsWithFibonacci: " + climbStairsWithFibonacci(n3));System.out.println("input: " + n3 + " climbStairsWithFibonacciFormula: " + climbStairsWithFibonacciFormula(n3));}

结果

input: 2 climbStairs: 2
input: 3 climbStairs: 3
input: 20 climbStairs: 10946
input: 20 climbStairsWithRecursion: 10946
input: 20 climbStairsWithRecursionMemory: 10946
input: 20 climbStairsWithDynamic: 10946
input: 20 climbStairsWithFibonacci: 10946
input: 20 climbStairsWithFibonacciFormula: 10946

总结

爬楼梯由最初的递归解法,
降低时间复杂度用了缓存优化,
降低方法调用栈溢出用了动态规划,
降低空间复杂度用了斐波那系数Fibonacci,
最后竟然有O(log(n))的时间复杂度优化方法Fibonacci Formula。

前人的经验,我们的阶梯。

代码下载:
https://github.com/zgpeace/awesome-java-leetcode/blob/master/code/LeetCode/src/ClimbingStairs.java

参考:
https://leetcode.com/problems/climbing-stairs/solution/

算法:Climbing Stairs(爬楼梯) 6种解法相关推荐

  1. LintCode Climbing Stairs 爬楼梯

    中文描述: 假设你正在爬楼梯,需要n步你才能到达顶部.但每次你只能爬一步或者两步,你能有多少种不同的方法爬到楼顶部? 样例 比如n=3,1+1+1=1+2=2+1=3,共有3中不同的方法 返回 3 E ...

  2. leetcode之Climbing Stairs爬楼梯

    题目链接 中文版题目链接 昨夜走在校园的小路上,灵感乍现,突然明白了为什么刚好是斐波那契数列可解此题. 普通思维: 走第一步时有两种情况,走一个台阶,或两个台阶: 走第二步时,第一步时的两种情况中又分 ...

  3. [LeetCode-70]-Climbing Stairs(爬楼梯,斐波那契数列问题)

    文章目录 题目相关 Solution 题目相关 [题目解读] 该题就是斐波那契数列问题,可以使用递归方法实现. [原题描述]原题链接 You are climbing a stair case. It ...

  4. 面试经典算法题--爬楼梯 的六种解法

    题目描述: 假设你正在爬楼梯,需要n步你才能到达顶部.但每次你只能爬一步或者两步,你能有多少种不同的方法爬到楼顶部? 六种解法: /*** 爬楼梯问题其实质就是斐波那契数列!*/ public cla ...

  5. java 爬楼梯算法_动态规划-爬楼梯问题java实现

    最近开始看算法导论,研究了一下动态规划,下面就开始直入主题开始记录近期看的第一个知识点动态规划.提起动态规划就不得不提几个动态规划的金典问题爬楼梯.国王金矿.背包问题.今天就仔细分析一下爬楼梯问题. ...

  6. 程序设计与算法----递归之爬楼梯问题

    爬楼梯 树老师爬楼梯,它可以每次走1级或者2级,输入楼梯的级数,求不同的走法数 例如:楼梯一共有3级,它可以每次都走一级,或者第一次走一级,第二次走两级,也可以第一次走两级,第二次走一级,一共有3种走 ...

  7. 一步一步写算法(之爬楼梯)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前两天上网的时候看到一个特别有意思的题目,在这里和朋友们分享一下: 有一个人准备开始爬楼梯,假 ...

  8. python爬楼梯多少种_Python 爬楼梯问题--有n阶台阶,上楼可以一步上1阶,2阶,3阶,计算共有多少种不同的走法?...

    Python爬楼梯问题:有n阶台阶,上楼可以一步上1阶,2阶,3阶,计算共有多少种不同的走法? 总共n步台阶(先假设n>3),f(n)表示n步台阶的走法总数 1.第一步如果是只走1步台阶,剩下的 ...

  9. 算法珠玑-变位词的四种解法

      给定一个英语词典,找出其中所有变位词集合.例如,"pots"."stops".和"tops"互为变位词,因为每一个单词都可以通过改变其他 ...

最新文章

  1. main方法为什么是静态的
  2. 真牛X!这款通用数据库连接工具DBeaver!可以连接和操作市面所有的数据库!...
  3. Deep Learning源代码收集-持续更新…
  4. springboot中注入FilterRegistrationBean不生效原因
  5. idea 导入template_如何将静态导入添加到IntelliJ IDEA实时模板
  6. vue计算属性与监听器的区别
  7. Spring入门看这一篇就够了
  8. 【论文翻译笔记】A Systematic Evaluation of StaticAPI-Misuse Detectors
  9. firework算法_FireWorks 自从烟花算法的开创性论文由谭营教授等人于2010年发表之后 联合开发网 - pudn.com...
  10. html如何格式化时间,js 日期时间的格式化
  11. [转]Oracle数据库逻辑增量备份之exp/imp
  12. windows局域网的一个经典的入侵方法
  13. curl myip.ipip.net curl ip.cn curl cip.cc
  14. 2021年最全圣诞节攻略,外贸人看这一篇就够了
  15. php srt,常见字幕文件格式(lrc、srt、ass)的区别以及互相转换的方法
  16. 如何分析线程Dump和堆Dump
  17. 使用A*算法求最短路径
  18. W7系统如何增大C盘空间(动态磁盘)
  19. 再一次被入侵之潜伏的挖矿病毒
  20. 疯狂的大柚柚带你玩转MSP-ESP430G2(基础篇) -----(六)基础知识补充

热门文章

  1. 从零开始开发SSM项目-博客系统实战
  2. Ethernet(以太网) 详解 MAC、MII、PHY
  3. Cookie,sessionstorage,localstorage,Token ,JWT,session的区别
  4. 倍福控制电机耦合运动
  5. Kibana7.9.2设置elasticsearch索引过期时间,到期自动删除
  6. 后羿采集器怎么导出数据_免费爬虫工具:后羿采集器如何采集同花顺圈子评论数据...
  7. 论微信小程序安装SSL证书的重要性
  8. 你听不出是AI在唱歌!这个日本虚拟歌姬,横扫中英日三种语言
  9. OBS录屏如何设置录制窗口大小?
  10. WIndows内核学习笔记:分页机制——PAE分页模式