第2章 数字之魅——斐波那契(Fibonacci)数列
斐波那契(Fibonacci)数列
问题描述
递归算法:
- package chapter2shuzizhimei.fibonacci;
- /**
- * Fibonacci数列递归求解
- * @author DELL
- *
- */
- public class Fibonacci1 {
- public static int fibonacci(int n){
- if(n<=0)
- return 0;
- else if(n==1)
- return 1;
- else
- return fibonacci(n-1)+fibonacci(n-2);
- }
- public static void main(String[] args) {
- int n = 3;
- System.out.println("fibonacci("+n+") = "+fibonacci(n));
- }
- }
我们的问题是:有没有更加优化的解法?
分析与解法
【解法一】递推关系的优化
上述递归算法中有着很多的重复计算,利用一个数组存储中间结果避免重复计算。时间复杂度为O(N),空间复杂度也为O(N)。
算法如下:
- package chapter2shuzizhimei.fibonacci;
- /**
- * Fibonacci数列求解
- * 【解法一】递推关系的优化
- * @author DELL
- *
- */
- public class Fibonacci2 {
- private static int f[];
- public Fibonacci2(int n){
- f = new int[n+1];
- for(int i=0;i<n;i++){
- f[i]=-1;
- }
- }
- public static int fibonacci(int n){
- if(n<=0){
- f[0]=0;
- return 0;
- }
- else if(n==1){
- f[1]=1;
- return 1;
- }
- else{
- if(f[n-1]==-1){
- if(f[n-2]==-1)
- return fibonacci(n-1)+fibonacci(n-2);
- else
- return fibonacci(n-1)+f[n-2];
- }else{
- return f[n-1]+f[n-2];
- }
- }
- }
- public static void main(String[] args) {
- int n = 3;
- new Fibonacci2(n);
- System.out.println("fibonacci("+n+") = "+fibonacci(n));
- }
- }
程序运行结果如下:
- fibonacci(3) = 2
【解法二】采用非递归求解
算法如下:
- package chapter2shuzizhimei.fibonacci;
- /**
- * Fibonacci数列求解
- * 【解法二】非递归
- * @author DELL
- *
- */
- public class Fibonacci3 {
- public static int fibonacci(int n){
- if(n<=0)
- return 0;
- else if(n==1)
- return 1;
- else{
- int f0 = 0,f1 = 1,f2 = 0;
- for(int i=2;i<=n;i++){
- f2 = f0 + f1;
- f0 = f1;
- f1 = f2;
- }
- return f2;
- }
- }
- public static void main(String[] args) {
- int n = 3;
- System.out.println("fibonacci("+n+") = "+fibonacci(n));
- }
- }
程序运行结果如下:
- fibonacci(3) = 2
【解法三】求解通项公式
算法代码如下:
- package chapter2shuzizhimei.fibonacci;
- /**
- * Fibonacci数列求解
- * 【解法三】求解通项公式
- * @author DELL
- *
- */
- public class Fibonacci4 {
- public static long fibonacci(int n){
- double x = Math.sqrt(5);
- double f = (x/5)*Math.pow((1+x)/2, n) - (x/5)*Math.pow((1-x)/2, n);
- return Math.round(f);
- }
- public static void main(String[] args) {
- int n = 3;
- System.out.println("fibonacci("+n+") = "+fibonacci(n));
- }
- }
程序运行结果如下:
- fibonacci(3) = 2
【解法四】分治策略
要先导入JAMA:Java矩阵包
- package chapter2shuzizhimei.fibonacci;
- import Jama.Matrix;
- /**
- * Fibonacci数列求解
- * 【解法四】分治策略
- * @author DELL
- *
- */
- public class Fibonacci5 {
- //求解矩阵A的n次方
- public static Matrix MatrixPow(Matrix A, int n){
- int m = A.getColumnDimension();
- Matrix result = new Matrix(m,m); //生成全为0的矩阵
- for(int i=0;i<m;i++){ //变成单位矩阵
- result.set(i, i, 1);
- }
- Matrix temp = A;
- while(n!=0){
- if((n&0x01)==1)
- result = result.times(temp); //矩阵的乘法
- temp = temp.times(temp);
- n >>= 1;
- }
- return result;
- }
- //计算Fibonacci数列
- public static long fibonacci(int n){
- if(n<=0)
- return 0;
- else if(n==1)
- return 1;
- else{
- Matrix A = new Matrix(2,2,1); //生成全为1的矩阵
- A.set(1, 1, 0);
- Matrix B = MatrixPow(A, n-1);
- return (long) B.get(0, 0);
- }
- }
- public static void main(String[] args) {
- int n = 5;
- System.out.println("fibonacci("+n+") = "+fibonacci(n));
- }
- }
程序运行结果如下:
- fibonacci(5) = 5
扩展问题
假设A(0)=1,A(1)=2,A(2)=2。对于n>2,都有A(K) = A(k-1) + A(k-2) +A(k-3)。
1. 对于任何一个给定的n,如何计算出A(n)?
2. 对于n非常大的情况,如n=260的时候,如何计算A(n) mod M (M<100000)呢?
问题1:非递归解法,代码如下:
- package chapter2shuzizhimei.fibonacci;
- /**
- * 扩展问题1求解
- * 非递归
- * @author DELL
- *
- */
- public class Fibonacci6 {
- public static int A(int n){
- if(n<=0)
- return 1;
- else if(n==1||n==2)
- return 2;
- else{
- int f0 = 1,f1 = 2,f2 = 2,f3 = 0;
- for(int i=3;i<=n;i++){
- f3 = f0 + f1 + f2;
- f0 = f1;
- f1 = f2;
- f2 = f3;
- }
- return f3;
- }
- }
- public static void main(String[] args) {
- int n = 4;
- System.out.println("A("+n+") = "+A(n));
- }
- }
程序运行结果如下:
- A(4) = 9
问题2:非递归解法,代码如下:
- package chapter2shuzizhimei.fibonacci;
- /**
- * 扩展问题2求解
- * 非递归
- * @author DELL
- *
- */
- public class Fibonacci7 {
- //计算A(n) mod m
- public static long A(long n,long m){
- if(n<=0)
- return 1;
- else if(n==1||n==2)
- return 2;
- else{
- long f0 = 1,f1 = 2,f2 = 2,f3 = 0;
- for(int i=3;i<=n;i++){
- f0 = f0%m;
- f1 = f1%m;
- f2 = f2%m;
- f3 = f0 + f1 + f2;
- f0 = f1;
- f1 = f2;
- f2 = f3;
- }
- return f3%m;
- }
- }
- public static void main(String[] args) {
- long n = (long) Math.pow(2, 10);
- long m = 100;
- System.out.println("A("+n+") = "+A(n,m));
- }
- }
程序运行结果如下:
- A(1024) = 97
第2章 数字之魅——斐波那契(Fibonacci)数列的更多相关文章
- 斐波那契(Fibonacci)数列的几种计算机解法
题目:斐波那契数列,又称黄金分割数列(F(n+1)/F(n)的极限是1:1.618,即黄金分割率),指的是这样一个数列:0.1.1.2.3.5.8.13.21.34.…….在数学上,斐波纳契数列以如下 ...
- 斐波那契(Fibonacci)数列的七种实现方法
废话不多说,直接上代码 #include "stdio.h" #include "queue" #include "math.h" usin ...
- 如何用Python输出一个斐波那契Fibonacci数列
a,b = 0, 1 while b<100: print (b), a, b = b, a+b
- 斐波那契 (Fibonacci)数列
尾递归会将本次方法的结果计算出来,直接传递给下个方法.效率很快. 一般的递归,在本次方法结果还没出来的时候,就调用了下次的递归, 而程序就要将部分的结果保存在内存中,直到后面的方法结束,再返回来计算. ...
- ACM/ICPC 之 数论-斐波拉契●卢卡斯数列(HNNUOJ 11589)
看到这个标题,貌似很高大上的样子= =,其实这个也是大家熟悉的东西,先给大家科普一下斐波拉契数列. 斐波拉契数列 又称黄金分割数列,指的是这样一个数列:0.1.1.2.3.5.8.13.21.34.… ...
- 2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci)
2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci) 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 找规律 找两个节点的lca,需 ...
- 递归函数练习:输出菲波拉契(Fibonacci)数列的前N项数据
/*====================================================================== 著名的菲波拉契(Fibonacci)数列,其第一项为0 ...
- [洛谷P3938]:斐波那契(fibonacci)(数学)
题目传送门 题目描述 小$C$养了一些很可爱的兔子.有一天,小$C$突然发现兔子们都是严格按照伟大的数学家斐波那契提出的模型来进行繁衍:一对兔子从出生后第二个月起,每个月刚开始的时候都会产下一对小兔子 ...
- HZOJ 斐波那契(fibonacci)
先说一个规律: 如图将每个月出生的兔子的编号写出来,可以发现一只兔子在哪一列他的父亲就是谁. 每列的首项可以通过菲波那契求得. 然后你就可以像我一样通过这个规律打表每个点的父亲,预处理出倍增数组,倍增 ...
随机推荐
- CSS选择器的兼容性
CSS 1 CSS2.1 CSS3 :hover 在IE6中只有a元素可用.E:empty 貌似在webkit核心浏览器中有些小bug.如果这个bug依然存在,不太确定如何测试.IE6不支持.clas ...
- SVM:从理论到OpenCV实践
(转载请注明出处:http://blog.csdn.net/zhazhiqiang/ 未经允许请勿用于商业用途) 一.理论 参考网友的博客: (1)[理论]支持向量机1: Maximum Marg ...
- 使用Ant发布hadoop代码到服务器
首先,搭建Ant环境: 1.1.下载antzip包,可以直接从官网下,也可以从我的csdn账号下载,这里我使用的Ant版本是:apache-ant-1.8.4-bin CSDN Ant 所需jar包下 ...
- iOS开发中使用Bmob RESTful API
简介 尽管Bmob已经提供了一套SDK供开发者使用,但有时候开发者可能希望能直接与Bmob后台进行直接交互,以达到某些特别的需求(直接操作_User表.同步网络请求等).而RESTful API可以使 ...
- MySQL锁问题最佳实践
最近一段时间处理了较多锁的问题,包括锁等待导致业务连接堆积或超时,死锁导致业务失败等,这类问题对业务可能会造成严重的影响,没有处理经验的用户往往无从下手.下面将从整个数据库设计,开发,运维阶段介绍如何 ...
- 惊艳的随机化方法 -World Search (homework-04)
homeword04-word search 0. 摘要 本次作业,要求完成一个word search的程序,具体要求是: 输入:一个包含20-60个单词的文件,各单词不大于20个字母,无空格. 输出 ...
- JavaScript快排与原生sort的测试
今天工作室断网!果断回宿舍,不然各种资料都没有.(他说将来会找到!)不好意思,又哼起来了.进入主题,大家都知道,快排是各种排序算法中,最高效的也是应用最广的,还有更重要的一点,面试特别爱考的! 其实大 ...
- Java设计模式----组合模式(Composit )
1. 组合模式定义: 组合模式,又叫合成模式,有时又叫部分-整体模式,主要用来描述部分与整体的关系. 定义:将对象组合成树形结构以示" 部分--整体 "的层次结构,使得用户对单个 ...
- UVALive 6910 Cutting Tree(离线逆序并查集)
[题目]:(地址:) http://acm.hust.edu.cn/vjudge/contest/view.action?cid=97671#problem/E [题意]: 给出多棵树和两类操作:操作 ...
- Protobuf一键生成代码bat文件
最近在摆弄Unity的Socket,需要用到Protobuf,一般都会有多个协议文件,所以研究了下bat的批处理,下面给出批处理文件代码: @echo off ::协议文件路径, 最后不要跟“\”符号 ...