斐波那契数列:费波那契数列由0和1开始,之后的费波那契系数就是由之前的两数相加而得出
举例: 0 1 1 2 3 5 8 …..
/**
* @name fib
* @description
* 求斐波那契数列第 n 项的值
* 斐波那契数列为 0 1 1 2 3 ... 第 0 项为 0;
*
* @param n
* @returns Number
* @递归的缺点当超过一定的值时,会造成栈溢出
*/
function fib( n ) {
if( typeof n !== 'number' || n < 0) {
return '';
}
var fib_n = function( cur, next, n) {
if(n === 0) {
return cur;
}
else {
// 调换参数位置并且 进行 next + cur 累加操作
return fib_n(next, next + cur, n - 1)
}
};
return fib_n( 0 , 1 , n);
}
/**
* @name fibBetter
* @description
* 求斐波那契数列第 n 项的值
* 斐波那契数列为 0 1 1 2 3 ... 第 0 项为 0;
*
* @param n
* @returns Number
* @循环不会造成栈溢出
*/
function fibBetter( n ) {
if( typeof n !== 'number' || n < 0) {
return '';
}
function fib_n(cur, next, index) {
while (index >= 0) {
var item = cur;
cur = next;
next = item + next;
index--;
}
return cur;
}
return fib_n(0, 1, n - 1);
}
斐波那契数列对应的台阶问题
假设有 n 阶台阶, 一次可以上小于等于m 个台阶, 问有多少种上法 ?
先假设 a 情景 只有 1 个台阶 一次可以上的台阶数定义为step, 且 0 < step <= 2的话, 一共有 1 种上法
假设 b 情景 只有 2 个台阶 一次可以上的台阶数定义为step, 且 0 < step <= 2的话, 一共有 2 种上法
假设 c 情景 只有 3 个台阶 一次可以上的台阶数定义为step, 且 0 < step <= 2的话,
那我们刚开始就只有 2 种 上法 即只上 1 个台阶 或只上 2 个台阶
再进一步假设我第一次只上了 1 个台阶,
后面的 2 阶台阶的上法不就等同于
前面假设的 b 情景的上法嘛, (暂且理解为简单的递归思想吧)
再假设我第一次上了 2 个台阶,剩下的 1 个台阶等同于 a 情景 ,
好了我这第一次能够上的台阶数假设完了,没有其他可能了,
那情景c的上法就是 情景a + 情景b 的上法,
即情景 c, 一共有 3 种上法。
假设情景 d 有 4 个台阶 一次可以上的台阶数定义为step, 且 0 < step <= 2的话,
通过情景 c 的假设方法, 我们不难得出 情景 d , 一共有 5 种上法
总结以上的结果可以得出台阶数 n 跟方法之间 ,可以是一个对应的斐波那契数列,只不过第 0 项是一个 1,
这样总结后我们,
可以写出有n阶台阶 ,一次可以上的台阶数定义为step, 且 0 < step <= 2的话,求总共有几种上法的函数
function step_2(n) {
var fib_n = function(curr, next, n)
{
if (n === 0)
{
return curr;
}
else
{
return fib_n(next, curr+next, n-1);
}
return fib_n(1, 1, n); //改动第0项为1即可
}
再来看看原先的问题
假设有 n 阶台阶, 一次可以上小于等于 m 个台阶, 问有多少种上法 ?
其实就是一道数学题!
假定 n <= m
, 那对于前 n - 1
个台阶每个都有两种走法,最后一个台阶必须走,那么就有 Math.pow(2, m - 1)
种走法。
剩下一种情况, n > m
, 根据总结,容易发现,其实方法数等于
Math.pow(2, m - 1) 减去 Math(2, 0) + Math.(2, 1) .... + Math(2, m - n -1)的和
好的没有其他情况了。
/**
* @name sum
* @descript
* 为的是应对 m < n 的情况,
* 求 Math(2, 0) + Math.(2, 1) .... + Math(2, m - n - 1)的和
* @param m 总的台阶数
* @param n 最大可以跨越的台阶数
* @returns {number}
*/
function sum( m, n) {
var len = m - n;
add = 0;
// 第一次循环先判断len 然后 len = len - 1赋值后进入循环体
while(len--) {
add += Math.pow(2, len);
}
return add;
}
/**
* @name methods
* @description
* 参数必须是 number 类型 且 大于 0 ,为了便于理解 函数内没有写限制条件
* 假设有 m 阶台阶, 一次可以上小于等于 n 个台阶, 问有多少种上法 ?
*
* 分两种情况 m <= n 直接返回 Math.pow(2, m - 1);
* 对于 m > n 直接返回 Math(2, m - 1) - sum(m , n);
* @param m 总的台阶数
* @param n 最大可以跨越的台阶数
* @returns {number}
*/
function methods( m , n ) {
var ret, i;
i = m - 1;
if ( m <= n) {
ret = Math.pow(2, i )
} else {
ret = Math.pow(2, i) - sum(m , n);
}
return ret;
}