人物介绍
斐波那契本人的介绍:人类历史中,意大利数学家斐波那契(Leonardo Fibonacci)是一个天才,年少时随着父亲在北非做生意,学习了阿拉伯数字。1202年(我国的南宋时期),他撰写了《Liber Abaci(算书)》一书,向西方传播印度-阿拉伯的数字系统。
js程序命名的时候最好不要用本人的名字命名,例如斐波那契,是为了纪念他在数学届的突出贡献
例如我们的抗日名将,原西北军,冯玉祥的的手下,三十三集团军,陆军中将,张自忠,北京、天津、上海、武汉为了纪念他,都已他的名字进行命名,所以我们在写程序的时候也不能用自己的名字进行命名
斐波那契数列
-
斐波那契数列举例
- 兔子数列 在《Liber Abaci(算书)》一书中,斐波那契提出了一个有趣的问题:有一对成年兔子,每隔一个月就生一对小兔子,而小兔子一个月后也成年了加入生小兔子的行列,如果每对兔子都经历这样的出生、成熟、生育的过程,并且永远不死,问N个月后有多少对兔子?我们不妨用树状图展示一下
用数列表示为:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144…...数列中的每一项都被称为斐波那契数,用符号Fn表示。F(0)=1,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N)。
这就是著名的斐波那契数列(Fibonacci数列),也叫做“兔子数列”。
兔子数列的解释
斐波那契数列有几个前提,
第一个前提就是有一对兔子,一公一母,这个远远不够,
第二个就是兔子隔一个月就会变大,变大以后就可以生兔子
第三个就是这对兔子每隔一个月就能生一对兔子,兔子一公一母,然后兔子长大以后就可以继续生
最后一个就是兔子永远都不会死掉会一直,存在
斐波那契数列兔子生的过程
首先是就是第一个月兔子还是一对,
第二个月以后还是一对,但是兔子会长大,
第三个月以后长大以后的兔子可以生一对兔子,这个时候 有一对大兔子和一对小兔子,这个时候就是两对兔子
到了第四个月后,大兔子继续生一对,算上之前的大兔子,这就是两对,还有之前的小兔子一共是三对
到了第五个月以后 大兔子继续生一对,还有这是两对,还有之前生的兔子,这就是三对,
之前的兔子隔了一个月长大后就可以生一对兔子,这又是两只,加在一起,用就是五只
...
就是斐波那契数列,得出的规律就是当前月的兔子的对数就等于前两月兔子对数之和
fn(n)=fn(n-1)+fn(n-2);
什么是递归
递归就是函数自己调用自己,还有就是当前的值就是上一次执行完的结果,我看下边的图:
例如我们的二百米接力,他是要等到上一一个人围着操场跑完,把接力棒给你,以后你才可以,真正的启动去跑,不然就是所有人都跑了,你也要在那里等着,也就是说,我们是等到上一次运行完,出来一个结果,给了我们以后,你才可以使用,第二次运行的时候就是要用第一次运行出来的值。
程序的实现
1、注意点儿问题第一个就是递归一定要有结束条件
2、第二就是找好递归运行规律
// var count=0;
var fn = function (n) {
// count++;
if (n == 0 || n == 1) {
return 1;
}
return fn(n - 1) + fn(n - 2);
};
console.log(fn(20));
如果第一个和第二个月的时候返回出来的兔子都是1对,其他情况下就是当前的兔子数量
等于上一个月兔子数量加上上两月兔子的数量
但是,这个会有一个很严重的问题,就是他会有大量的重复计算的过程,
比如第十个月就会拆分出来很多个三四个月,如果都需要进行计算,那计算机的压力就会变得很大,
所以,你在计算到40的时候,就很吃力,到了60以上基本上就需要很长时间了,
所以我们需要对这个递归进行优化,我们来看一下优化的方案把
let p1 = {}
// let count = 0
function fn(n) {
if (p1[n]) {
return p1[n]
} else {
// count++
if (n == 1 || n == 2)
return 1
p1[n] = fn(n - 1) + fn(n - 2)
return p1[n]
}
}
console.log(fn(1000))
首先我们找一个json对象,每次函数执行的时候我们都要看看当前月是否已经执行过,
如果已经执行过,那就,直接将数值直接返回出来,那这样会大大的降低代码执行的频率,否则的情况我们再让他进行递归计算
二分法
优点:比较次数少,查找速度快,平均性能好。
要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表
假如我们要查找26这个数字,首先我们先找到中间的位置,拿到中间的这个数字9和我们的26做下对比, 发现26要大于9,而且我们现在的数组的顺序是从小到大的顺序,所以我们现在,左边的数组就是不需要了, 再找的话,我们现在就可以从中间到右边去找了,这个时候,中间的这个数字也不需要,因为他不符合, 我们又开始找到他中间的位置的26,正好和我要找的数字是一样大的,所以这个时候就可以将26这个数字 的位置直接返回出来就可以了
我们在看一个图的动态演示
好我们开始上代码
var arr = [1,2,3,4,5,6,7,8,9,10,11,22,33,44];
var count=0;
function Find(arr,start,end,name){
count++;
if(start>end){
return -1;
}
var middle=Math.floor((start+end)/2);
if(arr[middle]==name){
return middle;
}else if(arr[middle]>name){
end=middle-1;
return Find(arr,start,end,name);
}else{
start=middle+1;
return Find(arr,start,end,name);
}
}
console.log(Find(arr,0,arr.length-1,11));
console.log(count)
首先我们需要准备一个有序的数组,从小到大的有序数组,准备一个这个递归函数,命名为Find把,
然后准备四个参数第一个参数就是 数组、第二个就是开始位置,第三个就是结束位置,还有
最后一个就是要查找的数值,首先我们还是比较一下,如果开始位置大于结束位置的时候,证明
这个时候是找不到的,所以直接返回负一,然后就是找到中间位置,并且向下取整,如果中间
的位置正好等于要找的那个值,此时就将中间的位置返回过来,如果中间的位置大于你要找的数字,
所以这边我们要留下左边,右边就不要,所以end就等于 中间位置减去一,还有要return 重新按照
原来的查找过程再次查找一次,否则就是中间位置小于要找的值,这个时候我们需要留下右边去重左边
然后start开始位置就等于中间位置加1然后按照之前的查找过程再次查找一次