爬楼梯 java_面试官在“逗”你系列:到底应该怎么爬楼梯?!

直奔主题

算法题是在面试过程中考察候选人逻辑思维能力、手写代码能力的一种方式,因为有一句古话说的好:“说一千道一万,不如写段代码看一看”。

138bf3475f0c088773ea7f7f230d6caa.png

今天我们就来个单刀直入,直奔主题,从一个真实面试题到底怎么爬楼梯来聊一聊算法中的动态规划 。

面试真题

小明家有一楼梯共有10级台阶,每次可以爬1级或2级,问小明爬到第10级台阶,一共有多少种走法?

为什么是“小明”呢?这是个奇怪的问题~

真题分析

很多同学在第一次遇到这个爬楼梯的问题可能会比较懵,不知道该如何来解决。我们首先需要做的就是寻找这个问题的关键点:每次只能爬1级或2级。

递归思想

小明每次只能爬1级或2级,那么对于爬到第10级台阶来说,最后一次操作为走1级(此时处于第9级台阶上)或走2级(此时处于第8级台阶上)。

假定我们有个表达式f可以来计算到达某阶台阶的走法,那么对于第10阶来说,这个表达式就应该为:f(10) = f(9) + f(8)。

对于这个表达式,是不是有种瞬间回到那初、高中的年代~

按如上规则,再次考虑,爬到第9级台阶时,最后一次操作为走1级(此时处于第8级台阶上)或走2级(此时处于第7级台阶上),此处的表达式为:f(9) = f(8) + f(7)。

......

依次处理,当爬到第3级台阶时,计算的表达式就是f(3) = f(2) + f(1)。

那爬到第2级台阶有几种方式呢:每次走1级或者一次走2级,也就是一共有2种走法,f(2) = 2。

爬到第1级台阶的方式肯定只有一种:走1级,f(1) = 1。

按我们的思考逻辑,相关代码如下:

/** * @method climbStairs * @description 爬楼梯 * @param {number} n 楼梯台阶数 * @return {number} 一共有多少种走法*/function climbStairs (n) { if (n === 1) { return 1 }; if (n === 2) { return 2 }; let num = 0; num = climbStairs(n - 1) + climbStairs(n - 2); return num;}// 调用函数,输出结果let num = climbStairs(10);console.log(num); // 89

Congratulations~我们已经完成啦,得到了正确的结果。

就在你满脸微笑、志得意满的向面试官讲解思路的时候,面试官十有八九会一副老狐狸得逞的样子,继续问你,假如n的值比较大的,如40之类的,上面定义的climbStairs的执行性能如何。

我们来看下执行的性能:

测试代码如下:

console.time();let num = climbStairs(40);console.log(num);console.timeEnd()

我的mac配置如下:

MacBook Pro 处理器:2.5 GHz 四核Intel Core i7内存: 16GB

连续执行三次数据如下:

序号

结果

执行时间

1

165580141

811.077ms

2

165580141

817.025ms

3

165580141

814.803ms

注:在执行过程中有卡顿,不是瞬间输出,如果执行的是```climbStairs(100)```,你应该会瞬间听到风扇启动的呜呜声

递归思想优化

在上面代码climbStairs的基础上我们来进行优化处理。我们仔细分析代码的执行流程,就会发现有很多重复计算的地方,比如说f(5)就会在f(6-1)、f(7-2)时被重复计算,这就浪费了时间和性能。

那我们就选择使用空间换时间的策略,设置对象numbers,保存爬到某级台阶的结果,避免重复计算,numbers对象的结果如下:

let numbers = { 1: 1, 2: 2}

优化后代码如下:

/** * @method climbStairs * @description 爬楼梯 * @param {number} n 楼梯台阶数 * @return {number} 一共有多少种走法*/function climbStairs (n) { // 存储计算的结果,key(台阶) : num(走法) let numbers = { 1: 1, 2: 2 }; let tmpClimbStairs = function (n) { // 已存在的数据,直接返回,不再重新计算 if (numbers[n]) { return numbers[n]; } // 不存在的数据,进行计算 let num = tmpClimbStairs(n - 1) + tmpClimbStairs(n - 2); // 计算完成后,存放如numbers中,下次可以直接使用 numbers[n] = num; // 返回结果 ret.........

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值