想要保持自己的技能活力,最有效的手段便是通过不断地输入来供应足够的养分。我们也不必刻意追求博识的或者新鲜的知识点,通过对一个根本问题的全方位多维度解析,同样也会收成不小。
题目
有这么一道题目须要我们来解答:
试输出斐波那契数列的前10项,即 1、1、2、3、5、8、13、21、34、55。剖析有些人看到题目中涌现了“斐波那契数列”这个观点后,可能脑袋就蒙圈了,实在大可不必!
对付这道题,可以不用理会这个陌生观点,我们只须要关心后面它给出的数字规律即可。
我们可以看到,规律总结起来就一句话:从第三位开始,后面每项的值即是前两项之和,用式子表示的话便是:an = an-1 + an-2(n ≥ 2) 。
根据题目哀求,实在便是要我们做两件事:
天生每一项的值。打印输出所有值。根本解法解题思路:
创建一个数组存放数列各项的值。for 循环天生数列各项并存入数组(为了打算后面各项的值),打印天生的项。代码实现如下:
/ @description 创建一个天生数列数组的方法 @param {number} n 表示要天生多少项(即数组长度,不是数组下标) /function createFibArr(n) { // 声明一个存放数据的数组 let fibArr = []; // 从第三项(下标为2)开始,每一项都即是前两项之和 for (let index = 0; index < n; index++) { index < 2 ? fibArr.push(1) : fibArr.push(fibArr[index - 1] + fibArr[index - 2]); console.log(fibArr[index]); }}// 调用方法createFibArr(10);
剖析:
这该当是最基本的解题方法,很随意马虎就实现了。
但如果这是口试题的话,这样的答案只能说是中规中矩,没有出彩的地方,最主要的是表示不出我们分歧凡响的气质啊,以是,我们该当用点其他的手段来提升下自己的逼格!
解题思路:
通过递归的手段打算出各位置对应的值(这里有个条件是:第一项和第二项是确定值,否则,递归就不好用了)。打印结果。代码实现如下:
/ @description 打算出第 n 项的值 @param {number} n 表示每一项的下标值 @returns {number} 下标为 n 的位置的值 /function calFibValue(n) { console.count("实行次数:") return n < 2 ? 1 : (calFibValue(n - 1) + calFibValue(n - 2));}/ @description 打印打算结果 @param {number} n 代表要打印多少项 /function printRes(n) { for (let index = 0; index < n; index++) { console.log(calFibValue(index)); }}// 调用打印方法printRes(10);// 实行次数:: 276
剖析:
递归的利用确实提升了代码的逼格,但是又引来了其余一个问题:性能问题。
每一项的值都是从第一项开始打算累加 出来的,比如打算第四项的值,其过程如下:
返回第一项的值:1 。返回第二项的值: 1 。打算第三项的值为 1 + 1 = 2 。打算第四项的值为 2 + 1 = 3 。在打算第五项值的时候,还要经由上面这个过程来获取第四项的值,进行了大量的重复运算。
为了惊艳口试官,我们还须要再做优化!
解题思路:
导致重复打算的是递归那部分的逻辑,以是优化点在递归这里。既然存在重复运算,那就意味着实在后面的运算完备可以利用前面已经打算出来的值,以是我们须要引入缓存来保存每次的打算结果。代码实现:
/ @description 打算出第 n 项的值 @param {number} n 表示每一项的下标值 @returns {number} 下标为 n 的位置的值 /// 存放每次打算结果的 Map 构造// 这里也可以用数组,但是在语义方面没有 Map 或工具直接let fibValueMap = new Map();function calFibValue(n) { console.count("实行次数:"); // 如果缓存中已存在对应的值,则直接返回 if (fibValueMap.has(n)) { return fibValueMap.get(n); } const value = n < 2 ? 1 : (calFibValue(n - 1) + calFibValue(n - 2)); // 在打算出每一项的之后,须要及时存入 Map fibValueMap.set(n, value); return value;}/ @description 打印打算结果 @param {number} n 代表要打印多少项 /function printRes(n) { for (let index = 0; index < n; index++) { console.log(calFibValue(index)); }}// 调用打印方法printRes(10);// 实行次数:: 26
剖析:
根据打印出来的 count 来看,优化后的递归次数是优化前的 1/10 旁边,这个结果就很惊喜了。
这次口试官该当可以满意了吧。
总结万变不离其宗,只要将解题思路理清了,代码实现只是一个结果而已。在平常的事情学习中,我们要故意识地培养自己的发散性思维,从多角度去看待问题,你可能会创造不一样的风景哦!
希望能够对大家有所启示哦!
在口试中,为了突显自己的独特气质或者人家口试题目就有详细哀求的,我们利用一些看起来高大上的思路,这无可厚非。
但是呢,在平常的事情中,我还是更建议大家:在性能附近的情形下,能利用根本方法办理的一样平常不要用“高档”方法,由于根本方法出错的概率小很多。就比如本日这道题,实在根本解法的性能是最好的。
少写 BUG,我们才能有更多的韶光来摸鱼,不是吗?
~
~ 本文完,感谢阅读!
~
学习有趣的知识,结识有趣的朋友,塑造有趣的灵魂!
我是〖编程三昧〗的作者 隐逸王,我的"大众年夜众号是『编程三昧』,欢迎关注,希望大家多多指教!
你来,怀揣期望,我有墨喷鼻香相迎!
你归,无论得失落,唯以余韵相赠!
知识与技能并重,内力和外功兼修,理论和实践两手都要抓、两手都要硬!