递归思想之---斐波拉契数列

斐波那契数列中的递归思想

??如果上述的分析都明白了,那就说明你已掌握了递归,但为了加深对递归的理解,我们再来看一个思考题(来自程序员的数学思考题),题目是这样的,假如动物中有一种特殊的种类,它出生2天后就开始以每天1只的速度繁殖后代。假设第1天,有1只这样的动物(该动物刚出生,从第3天开始繁殖后代)。那么到第11天,共有多少只呢?

我们先来按一般顺序思考,先不要考虑第11天,先从第1天开始,看能不能找出规律:
【第1天】只有1只动物
【第2天】只有1只动物,还没有繁殖后代,总量为1
【第3天】第1天的1只动物,繁殖1个后代,总量为2
【第4天】第1天的1只动物又繁殖1只,其他还没繁殖,总量为3
【第5天】第1天和第3天出生的动物又繁殖1个后代,其他没有繁殖,总量为5
【第n天】.....

 第1天 ------1
 第2天 ------1
 第3天 ------2 = 1 + 1
 第4天 ------3 = 1 + 2
 第5天 ------5 = 2 + 3
 第6天 ------8 = 3 + 5
 第7天 ------13 = 5 + 8

?? 这个过程中貌似没发现什么规律,但我们发现从第3天开始动物的数量似乎前两天的总和,也就是第3天,是第1天的动物数量加上第2天的动物数量,而第4天则是第2天和第3天的动物数量的和。这样的话我们可以归纳一下,不去直接想”第n天有多少只动物“而是如下思考:

  • 第n-1天出生的动物,在第n天还存活着。
  • 第n-2天以前出生的动物,在第n天繁殖了后代

??因此可以总结出递推公式,假设在第n天时,第n-1天以前繁殖的动物都活着,并且第n-2天以前出生的动物会繁殖1个后代,设第n天的动物总数为F(n),则有:F(n)=F(n-1)+F(n-2) 其中 n>=3,如下图所示 

注意为了让F(2)=F(1)+F(0)成立,定义F(0)=0,而F(1)则依然为1,因此有如下公式: 

我们来验证这个递推公式是否符合递归条件

  • ①边界条件:至少有一条初始定义是非递归的,F(0)=0;F(1)=1。
  • ②递归通式:由已知函数值逐步计算出未知函数值,F(0)=0;F(1)=1,可以推算出F(2)=1,最终也可以推算F(n)的结束。

显然两个条件都符合,说明该通用公式可以在有限的次数内运算完成并达到边界条件得出结果,因此我们可以利用递推公式求出第11天的动物的数量:

F(0)=0
F(1)=1
F(2)=F(0)+F(1)=1
F(3)=F(2)+F(1)=2
F(4)=F(3)+F(2)=3
F(5)=F(4)+F(3)=5
F(6)=F(5)+F(4)=8
F(7)=F(6)+F(5)=13
F(8)=F(7)+F(6)=21
F(9)=F(8)+F(7)=34
F(10)=F(9)+F(8)=55
F(11)=F(10)+F(9)=89

也就是说第11天的动物总数为89只

在这个问题中出现的数列就是著名的斐波那契数列,是由数学家斐波那契发现的,由此得名斐波那契数列。

0 ,1 ,1 ,2 ,3 ,5 ,8,13 ,21 ,34 ,55 ,89 ,…

??到此我们也就知道斐波那契数列同样是用递归定义的,前面我们将求解第n天的动物数量分解为求第n-1天和第n-2天以前的动物繁殖后代数量,从把复杂的问题分解为较为简单的同类问题,而不去纠结第n天到此有多少只动物的问题,最终发现求解的规律,并通过递推公式求得第n天的结果,这个过程再次体现了递归的思维方式。既然斐波那契数列是递归思维的产物,那么也可以通过程序的递归算法来求解,接下来我们就看看如何使用程序中的递归算法来实现斐波那契数列。

斐波那契数列的递归程序实现

实现代码比较简单就不过多分析了,代码如下:

package com.zejian.structures.recursion;

/**
 * Created by zejian on 2016/12/11.
 * Blog : http://blog.csdn.net/javazejian [原文地址,请尊重原创]
 * 斐波那契数列的实现
 */
public class Fibonacci  {

    /**
     * 斐波那契数列的实现
     * 0,1,1,2,3,5,8,13,21......
     * @param day
     */
    public long fibonacci(int day){

        if(day==0){ //F(0)=0
            return 0;
        }else if (day==1||day==2){//F(1)=1
            return 1;
        }else {
           return fibonacci(day-1)+fibonacci(day-2); //F(n)=F(n-1)+F(n-2)
        }
    }

    /**
     * 更为简洁的写法
     * @param day
     * @return
     */
    public long fib(int day) {
        return day== 0 ? 0 : (day== 1 || day==2 ? 1 : fib(day - 1) + fib(day - 2));
    }

    //测试
    public static void main(String[] args){
        Fibonacci fibonacci=new Fibonacci();
        System.out.println("第11天动物数量为:"+ fibonacci.fib(11));
        System.out.println("第11天动物数量为:"+ fibonacci.fibonacci(11));
    }
}

原文地址:https://www.cnblogs.com/Darkqueen/p/9517780.html

时间: 2024-07-30 13:47:40

递归思想之---斐波拉契数列的相关文章

斐波拉契数列的递归、非递归、公式法多种方法实现

实现斐波拉契数列:1,1,2,3,5,8...,当n>=3时,f(n)=f(n-1)+f(n-2). 解:求解斐波拉契数列方法很多,这里提供了4种实现方法和代码,由于第5种数学公式方法代码太过繁琐,只做简单介绍 方法一:递归调用,每次递归的时候有大量重复计算,效率低,可将其调用的过程转化成一颗二叉树进行分析,二叉树的总结点个数不超过(2^n-1)个,由于其是不完全二叉树,那么函数计算的次数必小于(2^n-1),时间复杂度为O(2^n):递归调用的深度为n,空间复杂度为O(n) 方法二:非递归数组

【动态规划专题】1:斐波拉契数列问题的递归和动态规划

<程序员代码面试指南--IT名企算法与数据结构题目最优解> 左程云 著 斐波拉契数列问题的递归和动态规划 [题目]:给定整数N,返回斐波拉契数列的第N项.补充问题1:给定整数N,代表台阶数,一次可以跨2个或者1个台阶,返回有多少种走法.补充问题2:假设农场中成熟的母牛每年只会生产1头小母牛,并且永远不会死.第一年农场只有1只成熟的母牛,从第2年开始,母牛开始生产小母牛.每只小母牛3年后成熟又可以生产小母牛.给定整数N,求出N年后牛的数量. [举例]斐波拉契数列f(0)=0, f(1)=1,f(

C# — 用递归实现斐波拉契数列的第n项

斐波拉契数列:1,1,2,3,5,8,13,21,34,55....... 规律:f(n)=f(n-1)+f(n-2) C# 代码实现: 原文地址:https://www.cnblogs.com/hh8888-log/p/11038915.html

递归1.2用递归函数来实现获取斐波拉契数列中第n个数字的值

用递归函数来实现获取斐波拉契数列中第n个数字的值 ps(斐波那契数列:从3三个数开始,后一个数等于前面两个数的和: 0,1,1,2,3,5,8,13,21,34,55,89,144……) def add(n): if n > 2: return (add(n-1) + add(n-2)) if n == 2: return 1 if n == 1: return 0 b = int(input("请输入一个数字")) print(add(b)) 结果输出: 请输入一个数字10 3

斐波拉契数列加强版——时间复杂度O(1),空间复杂度O(1)

对于斐波拉契经典问题,我们都非常熟悉,通过递推公式F(n) = F(n - 1) + F(n - 2),我们可以在线性时间内求出第n项F(n),现在考虑斐波拉契的加强版,我们要求的项数n的范围为int范围内的非负整数,请设计一个高效算法,计算第n项F(n).第一个斐波拉契数为F(0) = 1. 给定一个非负整数,请返回斐波拉契数列的第n项,为了防止溢出,请将结果Mod 1000000007. 斐波拉契数列的计算是一个非常经典的问题,对于小规模的n,很容易用递归的方式来获取,对于稍微大一点的n,为

c语言:写一个函数,输入n,求斐波拉契数列的第n项(5种方法,层层优化)

写一个函数,输入n,求斐波拉契数列的第n项. 斐波拉契数列:1,1,2,3,5,8...,当n大于等于3时,后一项为前面两项之和. 解:方法1:从斐波拉契数列的函数定义角度编程 #include<stdio.h> int fibonacci(int n) { int num1=1, num2=1, num3=0,i; if (n <= 2) { printf("斐波拉契数列的第%d项为:%d\n",n,num1); } else { for (i = 2; i <

Fibonacci斐波拉契数列----------动态规划DP

n==10 20 30 40 50 46 体验一下,感受一下,运行时间 #include <stdio.h>int fib(int n){ if (n<=1)     return 1; else            return fib(n-1)+fib(n-2); }int main( ){ int n; scanf("%d",&n); printf("%d\n" ,fib(n) );} 先 n==10 20 30 40 50 46

青蛙跳台阶问题-斐波拉契数列

题目1:一个台阶总共有n级,如果一次可以跳1级,也可以跳2级.求总共有多少种跳法 首先我们考虑最简单的情况,加入只有1级台阶,那显然只有一种跳法,如果有2级台阶,那就有两种跳的方法了:一种是分两次跳,每次跳1级:另外一种就是一次跳2级 现在我们来讨论一般情况.我们把n级台阶时的跳法看成是n的函数,记为f(n).当n>2时,第一次跳的时候就有两种不同的选择:一是第一次只跳1级,此时跳法数目等于后面剩下的n-1级台阶的跳法数目,即为f(n-1):另外一种选择是第一次跳2级,此时跳法数目等于后面剩下的

浅谈C#中的斐波拉契数列

突然对那些有趣的数学类知识感兴趣了,然后就简单研究了一下斐波拉契数列,看看它的有趣之处! 斐波拉契数列(Fibonacci Sequence),又称黄金分割数列,该数列由意大利的数学家列奥纳多·斐波那契发现的.这种数列指的是这样一个数列:0.1.1.2.3.5.8.13.21. 34.--在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2,n∈N*). 用C#实现斐波拉契数列的代码: Console.Write("请输入一个长