Fibonacci数列的解法:

 1、递归算法

 递归的概念,我说不清楚,语文不好。但是核心思想,我认为就是入栈出栈。比方说,你想要求得某个结果,如果一步求解不出来,那么先把最后一步的计算步骤进栈,先不考虑   它。转而去想,在求解最后一步之前的那一步应该怎么去做,就好比冬天穿衣服,再最后一步穿羽绒服之前我想大部分人会先穿一个羊毛衫(要是较真的话,内衣你应该会穿的吧)。这样,我们先把羽绒服放在一边(进栈),先去准备穿羊毛衫。然后,我们又发现在穿羊毛衫之前,我得穿个保暖内衣啊。好,我们再将羊毛衫先放一边(再进栈,此时羊毛衫在羽绒服上面放着)。这时候,我们穿上了保暖内衣,ok一下个——>栈的后入先出规则表示下一个我应该穿羊毛衫,ok穿上再下一个——>羽绒服。。。(下半身的穿衣流程类似,可能多一个胖次,自行脑补思考)。

 所以你看,现实当中很多时候的事情不是一下就可以完成的,而是需要一步一步的去完成,程序更是如此。你设计的代码,目的就是为了解决一个问题,在解决的过程中,会要进行很多的步骤,递归也是这样,只是它在解决问题之前一直在调用自身。

来看一下这个Fibonacci数列:

  Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。

  当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少。

第一步,n是多少。按照题目意思,自己输入n。

第二步,怎么求,这里我假设有这么一个方法就叫做Fibonacci(int n),return一个int,将n传进去之后,经过这个方法后,我就得到了Fn。

第三步,分析一下,Fn=Fn-1+Fn-2=Fn-2+Fn-3+Fn-3+Fn-4=..........所以,要求Fn(羽绒服),先去求Fn-1和Fn-2(羊毛衫),要求Fn-1就要先去求Fn-2和Fn-3,以此类推,暂时      求不出来的,统统依次入栈,最后发现要求F3,我得先求F2和F1(F3入栈)。OK,F1=F2=1,F3就求出来了(F3出栈),又F4=F3+F2,F4也求得出来了(F4出栈).......之前入    栈的那些步骤,再依次出栈进行计算,直到Fn被求出来,计算Fn%10007本题结束。

第四步,放代码:

import java.util.Scanner;

public class Fibonacci {
//Fibonacci数列 递归算法
public static int Fibonacci (int n){
if(n==1||n==2){
return 1;
} else{
//操作入栈出栈的核心,递归调用
n = Fibonacci (n-1)+Fibonacci (n-2);
return n;
}
} public static void main(String[] args) {
while(true){
Scanner scanner = new Scanner(System.in);
int n;
n = scanner.nextInt();
int k = Fibonacci (n);
System.out.println(k%10007);
} } }

  

 2、整数求余

递归的算法虽然代码简洁,但是有一个比较不太好的地方,就是执行的效率很低,它是自身层层深入的调用,在时间和空间上的复杂度都很高,而且计算的重复性操作很多,在计算机内部还很有可能造成栈溢出的现象。比方说,用递归的方法计算N阶计算的时候,当N的值越来越大,很可能计算机就罢工了。

所以,本着递归和循环理论相同的原则,结合整数求余的规律,将代码改进如下:

import java.util.Scanner;

public class Fibonacci {
//Fibonacci数列 求余算法
public static int Fibonacci(int n){
int[] F = new int[n+1];//n+1是为了不让数组出现越界
F[1]=F[2]=1;
for(int i=3;i<=n;i++){
F[i] = (F[i-1] + F[i-2])%10007;
}
return F[n];
}
public static void main(String[] args) {
while(true){
Scanner scanner = new Scanner(System.in);
int n;
n = scanner.nextInt();
System.out.println(Fibonacci(n)); } } }

在方法里面定义一个长度为n+1的int型数组,用来存储数列的值,其中n+1是为了防止数组在执行过程当中产生越界的现象。然后,方法里面的核心在于整数求余的计算,即:

F[i] = (F[i-1] + F[i-2])%10007;

为什么这样写?当代码改进成这样时,我们就不需要先求得Fn的值再去取余数,而是直接在for循环中,直接就能将取余的运算执行,当循环结束。最后得到的Fn,就是数列中第N个数取余的结果。
为什么可以这样写?这里面是有整数取余运算的规律的,举个例子,1%10取余数就是1,2%10就是2,3%10就是3,那是不是3%10=1%10+2%10?再多举几个例子来进行验证:

5%10=5;10%10=0;15%10=5=5%10+10%10;
21%10=1;32%10=2;53%10=3=21%10+32%10;
57%7=1;89%7=5;146%7=6=57%7+89%7;
......
可以看到,好像的确是这样,这当中的原理,其实你思考一下是可以理解的,但是我说不太清楚,害怕误人子弟,想要深入理解,可以百度。
附加我找的一位前辈的博客链接,记录了取余运算规则:https://blog.csdn.net/ash_zheng/article/details/38541777
暂时就写到这了,欢迎评论交流,互相学习,哈哈。

Fibonacci数列的解法的更多相关文章

  1. 【编程题目】题目:定义 Fibonacci 数列 输入 n,用最快的方法求该数列的第 n 项。

    第 19 题(数组.递归):题目:定义 Fibonacci 数列如下:/ 0 n=0f(n)= 1 n=1/ f(n-1)+f(n-2) n=2输入 n,用最快的方法求该数列的第 n 项. 思路:递归 ...

  2. 青蛙跳台阶(Fibonacci数列)

    问题 一只青蛙一次可以跳上 1 级台阶,也可以跳上2 级.求该青蛙跳上一个n 级的台阶总共有多少种跳法. 思路 当n=1时,只有一种跳法,及f(1)=1,当n=2时,有两种跳法,及f(2)=2,当n= ...

  3. 程序员面试题精选100题(16)-O(logn)求Fibonacci数列[算法]

    作者:何海涛 出处:http://zhedahht.blog.163.com/ 题目:定义Fibonacci数列如下: /  0                      n=0 f(n)=      ...

  4. 【费式数列(Fibonacci数列)】

    /* 说明: Fibonacci为1200年代的欧洲数学家,在他的着作中曾经提到:若有一只兔子每个月生一只小兔子,一个月后也开 始生产.起初只有一只兔子,一个月后就有两只兔子,二个月后就有三只兔子,三 ...

  5. 常系数线性递推的第n项及前n项和 (Fibonacci数列,矩阵)

      (一)Fibonacci数列f[n]=f[n-1]+f[n-2],f[1]=f[2]=1的第n项的快速求法(不考虑高精度). 解法: 考虑1×2的矩阵[f[n-2],f[n-1]].根据fibon ...

  6. Fibonacci 数列算法分析

    /************************************************* * Fibonacci 数列算法分析 ****************************** ...

  7. 可变长度的Fibonacci数列

    原题目: Write a recursive program that extends the range of the Fibonacci sequence.  The Fibonacci sequ ...

  8. 入门训练 Fibonacci数列

      入门训练 Fibonacci数列   时间限制:1.0s   内存限制:256.0MB 问题描述 Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1. 当n比较大时, ...

  9. fibonacci 数列及其应用

    fibonacci 数列及其延展 fibonacci计算 fibonacci数列是指 0,1,1,2,3,5,8,13,21……这样自然数序列,即从第3项开始满足f(n)=f(n-1)+f(n-2): ...

随机推荐

  1. 【Unity Shaders】Diffuse Shading——漫反射光照改善技巧

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  2. 【重构】 代码的坏味道总结 Bad Smell (一) (重复代码 | 过长函数 | 过大的类 | 过长参数列 | 发散式变化 | 霰弹式修改)

    膜拜下 Martin Fowler 大神 , 开始学习 圣经 重构-改善既有代码设计 . 代码的坏味道就意味着需要重构, 对代码的坏味道了然于心是重构的比要前提; . 作者 : 万境绝尘 转载请注明出 ...

  3. Android和iOS中Cocos2D日志为什么会出现skip frames

    在你运行app在Android或iOS设备或iOS模拟器中时,日志里往往会出现一行: I/Choreographer(28956): Skipped 159 frames! The applicati ...

  4. 01_MUI之Boilerplate中:HTML5示例,动态组件,自定义字体示例,自定义字体示例,图标字体示例

     1安装HBuilder5.0.0,安装后的界面截图如下: 2 按照https://www.muicss.com/docs/v1/css-js/boilerplate-html中的说明,创建上图的 ...

  5. SwipeRefreshLayout实现上拉下拉刷新

    1:在布局中添加SwipeRefreshLayout和Listview组件 [html] view plain copy <?xml version="1.0" encodi ...

  6. AngularJS进阶(十四)AngularJS灵异代码事件

    AngularJS灵异代码事件 注:请点击此处进行充电! 事情原委 router_sys.js源代码如下: 自己在html路由跳转的代码如下: 但是在实际路由过程中,却路由到了下面的状态,相应的页面中 ...

  7. web.xml 详细介绍

    url:http://mianhuaman.iteye.com/blog/1105522#bc2344393 1.启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<l ...

  8. 基于友善之臂ARM-tiny4412--uboot源码分析

    /* * armboot - Startup Code for OMAP3530/ARM Cortex CPU-core * * Copyright (c) 2004 Texas Instrument ...

  9. ROS探索总结(十一)——机器视觉

    机器视觉在计算机时代已经越来越流行,摄像头价格越来越低廉,部分集成深度传感器的混合型传感器也逐渐在研究领域普及,例如微软推出的Kinect,而且与之配套的软件功能十分强大,为开发带来了极大的便利.RO ...

  10. ZooKeeper 数据模型

    本文主要讲述ZooKeeper的数据模型,包括ZooKeeper的数据视图,节点的层次结构以及节点类型等基本属性.Zookeeper的视图结构类似标准的Unix文件系统,但是没有引入文件系统相关概念: ...