当前位置: 首页 > news >正文

前端算法 | LeetCode第 70 题爬楼梯问题

目录

流程分析

归纳法分析

为什么是斐波那契数列?

推导过程:

解法1:循环累加计算

解法2:递归计算

解法3:利用数组特性

解法4:利用 JavaScript ES6 新特性

拓展知识:每次可以走 1 步、2 步、3 步

拓展知识:斐波那契数列


 

本题为 LeetCode第70题爬楼梯,题目如下:

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

大家可以先想想

流程分析

本题中,可以每次可以走 1 级,也可以一次走 2 级,因此我们会有 3 种走法:

  • 全程任意走,如全部 1 级走;
  • 前面任意走,最后一步只走 1 级;
  • 前面任意走,最后一步只走 2 级;

我画了几张图方便大家理解,如下:

第一种走法就不做详细介绍。

第二种走法,倒数第二步的走法如下,有 1 步和 2 步两种方式:

第三种走法,倒数第二步的走法如下,也有 1 步和 2 步两种方式:

上面这个过程描述的是,从最后一层开始往下的每一层的走法。

在最后一步时,有 1 步和 2 步两种方式,可以理解为只能 1 步或者 2 步到达最后一层。

  • 当最后一步为 1 步时,即从 n-1 层开始;
  • 当最后一步为 2 步时,即从 n-2 层开始;

再理解一下这个过程,就是第 n 层的走法数量是第 n-1 层和第 n-2 层走法数量之和。

如果还不太理解,可以再看看前面的图。

归纳法分析

当然,遇事不决,归纳法走起,我们可以列举几种情况进行分析:

台阶层数走法数量走法
111
2211、2
33111、12、21
451111、112、121、211、22
5811111、1112、1121、1211、2111、221、212、122
.........

可以发现有个简单的规律,当台阶层数为 n 层,它的走法数量就有 n-1 层的走法数量加上 n-2 层的走法数量。

记做:f(n)=f(n-1)+f(n-2)

想象一下,你站在楼梯的底部,楼梯顶部有n个台阶。你可以选择每次走1个台阶或者2个台阶。问题是,你有多少种不同的方法可以走到顶部。

为什么是斐波那契数列?

  1. 第一步:如果你现在只有1个台阶(n=1),你只有一种方法,那就是直接走上去。所以,f(1)=1。
  2. 第二步:如果你有2个台阶(n=2),你有两种方法:先走1个台阶再走1个台阶,或者直接走2个台阶。所以,f(2)=2。

推导过程:

  • 当你走到第3个台阶(n=3)时,你可以从第1个台阶走两个2个台阶上来,或者从第2个台阶走一个1个台阶上来。所以,f(3)=f(2)+f(1)
  • 同理,当你走到第4个台阶(n=4)时,你可以从第2个台阶走两个2个台阶上来,或者从第3个台阶走一个1个台阶上来。所以,f(4)=f(3)+f(2)

这个逻辑可以一直延续下去,每次你到达一个新的台阶,你可以选择从上一个台阶走1步上来,或者从上上一个台阶走2步上来。这就是为什么这个问题的解法是斐波那契数列,因为每一步的解都依赖于前两步的解。

简单来说,爬楼梯问题就像是你在玩一个数字游戏,每一步的“分数”都是前两步“分数”的和。这就是为什么我们说爬楼梯问题是斐波那契数列的一个实际应用。

解法1:循环累加计算

通过简单的循环累加就能得到结果:

const climbStairs = (n = 1) => {if (n <= 2) return n;let res = 0,n1 = 1,n2 = 2; // n1 表示前 2 项,n2 表示前 1 项for (let i = 3; i <= n; i++) {// 前两项值固定,因此从第 3 项开始循环res = n1 + n2;n1 = n2;n2 = res;}return res;
};

 

解法2:递归计算

按照 f(n)=f(n-1)+f(n-2),这个方法更加简单:

const climbStairs = (n = 1) => {if (n <= 2) return n;return climbStairs(n - 1) + climbStairs(n - 2);
};

这个方法比较简洁易懂,但递归比较费时,容易出现 LeetCode 超出时间限制的提示。

解法3:利用数组特性

利用 f(n)=f(n-1)+f(n-2) 这个规律,先预设好前 2 项,再开始循环,最后返回数组最后一项即可:

const climbStairs = (n) => {let result = [1, 2];for (let i = 2; i < n; i++) {result.push(result[i - 1] + result[i - 2]);}return result[n - 1];
};

解法4:利用 JavaScript ES6 新特性

利用数组结构赋值操作: [a, b] = [c, d]

const climbStairs = n => {let a = b = 1;for (let i = 0; i < n; i++) {[a, b] = [b, a + b];}return a;
};

拓展知识:每次可以走 1 步、2 步、3 步

这里多增加了一次可以走 3 步,这时候最后一步会有以下情况:

  • 当最后一步为 1 步时,即从 n-1 层开始;
  • 当最后一步为 2 步时,即从 n-2 层开始;
  • 当最后一步为 3 步时,即从 n-3 层开始;

改造一下前面解法,还是一样:

const climbStairs = (n = 1) => {if(n <= 2) return n;if(n == 3) return 4;return climbStairs(n-1) + climbStairs(n-2) + climbStairs(n-3);
}

拓展知识:斐波那契数列

这一题主要考察的内容类似斐波那契数列(Fibonacci sequence)的计算,如果你还不清楚什么是斐波那契数列,这边先简单介绍一下,另外推荐

最早是有由数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入的,数列大致如:0、1、1、2、3、5、8、13、21、34、....。
认真观察,我们可以发现一个规律:从第 3 项开始,每一项的值都等于前两项之和

在自然界中,存在着许许多多的斐波那契数列的排列方式,比如一棵普通的树,它的树枝生长情况就像下面这样:

1.jpg

可以看到每一层枝干的数量为 1、2、3、5、8、...排列下去。当然还有很多其他的:

根据斐波那契数列的规律,得到这样的公式 f(n)=f(n-1)+f(n-2) 。跟我们前面列的差不多。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 骑行耳机品牌前五名排行榜:5大优质骑行耳机闭眼入都不踩雷!
  • 哈佛大学年中回顾2024年ESG发展近况
  • 导出word格式的Javadoc(可用于快速生成项目详细设计文档)
  • Swoole 和 Java 哪个更有优势呢
  • 白骑士的HTML教学高级篇 3.4 性能优化
  • 音频分割怎么弄?手把手教会你实用的音频分割技巧
  • 5G毫米波测试助力突破高频段设备局限,实现高效外场测试
  • Json-复杂泛型解析工具类
  • Gaussian Splatting 在 Ubuntu22.04 下部署
  • 回顾加密风险投资15年演变:步履维艰,但总体向上
  • 存储管理功能
  • Redis 作为 PHP 的会话存储
  • ctypes简单学习
  • 免费的开源报表工具都有哪些?盘点一下打工人必备的几款开源报表工具!
  • 【日记】黑神话的优化感觉有些微妙(1188 字)
  • 78. Subsets
  • Android开源项目规范总结
  • HTTP那些事
  • python_bomb----数据类型总结
  • React-flux杂记
  • Vue小说阅读器(仿追书神器)
  • WebSocket使用
  • XML已死 ?
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 代理模式
  • 多线程 start 和 run 方法到底有什么区别?
  • 前端技术周刊 2019-01-14:客户端存储
  • 为视图添加丝滑的水波纹
  • 我是如何设计 Upload 上传组件的
  • Java性能优化之JVM GC(垃圾回收机制)
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • ​马来语翻译中文去哪比较好?
  • # 达梦数据库知识点
  • #### go map 底层结构 ####
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • (C语言)fread与fwrite详解
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (二)PySpark3:SparkSQL编程
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (四)opengl函数加载和错误处理
  • (五)activiti-modeler 编辑器初步优化
  • (转)jdk与jre的区别
  • (转)四层和七层负载均衡的区别
  • ***原理与防范
  • .[hudsonL@cock.li].mkp勒索加密数据库完美恢复---惜分飞
  • .Net CF下精确的计时器
  • .net/c# memcached 获取所有缓存键(keys)
  • .NET中的十进制浮点类型,徐汇区网站设计
  • //usr/lib/libgdal.so.20:对‘sqlite3_column_table_name’未定义的引用
  • @Import注解详解