递归解决斐波那契数列

1、什么是递归?

  递归:递归是方法定义调用方法本身的现象。递归举例如下:

<span style="font-size:14px;">public class DiGuiDemo {

	//递归方法举例
	 public void show()
	 {
	     show();
	 }
}
</span>

2、递归的注意事项?

(1)递归一定要有出口。否则就会死递归。

  上面举例用的递归就是一个死递归,方法永远都在进行自身调用,最终一定会陷入内存崩溃。所以递归要定义出口,就是结束递归的条件。举例如下:

<span style="font-size:14px;">            public void show(int n)
 			{
 				if(n==0)
 				{
 					System.exit(0);
 				}
 				else{
 					System.out.println("hell");
 					show(n-1);
 				}
 			}</span>

  这个例子就是给show方法传递一个参数,每次递归参数减1,当参数为0时,退出。

(2)递归的次数不要过多,否则调用方法太多会导致内存空间溢出。

(3)构造方法不能使用递归的方式调用。

3、生活中存在的递归与递归思想?

  编程思想来源于生活,生活中有很多的递归小例子,例如小时候经常听的故事:

  从前有座山,山上有座庙,庙里有个老和尚,老和尚给小和尚讲故事:从前有座山,山上有座庙,庙里有个老和尚,老和尚给小和尚讲故事:从前有座山,山上有座庙,庙里有个老和尚,老和尚给小和尚讲故事。。。。。

  这就是递归了,可惜这个故事没有递归出口。。。

  递归的思想:编程取材于生活然后解决特定问题,在编程中递归是将大问题分解成若干的小问题,然后再将小问题分解成更小的问题,直到分解的问题是已知的结论。

4、练手:用递归求5!

  分析:(1)规律 :n!=n(n-1)!   (2)出口:当递归到1!时是已知的,1!=1。

  思路:将5!分解为5*4!;再将5*4!分解为5*4*3!。。。如图:

  代码体现:

<span style="font-size:14px;"> public class DiGuiDemo {
	public static void main(String[] args) {
		int num = 5;
		System.out.println(jc(num));
	}

        //定义求阶乘方法
	public static int jc(int n) {
		if (n == 1) {

			return 1; <span style="font-family: Arial, Helvetica, sans-serif;">// 出口 ,如果是1,就返回1</span>

		} else {

			return n * jc(n - 1);  <span style="font-family: Arial, Helvetica, sans-serif;">// 规律,如果不等于1,就递归</span>

		}
	}
}</span>

  对于阶乘方法来说,求n的阶乘,就返回n*(n-1)!,体现在递归上就是n*jc(n-1),当递归到1时,返回1。这个过程在内存中解析应该是:

  DiGuiDemo类被加载到方法区中,当执行此类时,首先将main方法调用到栈中执行,main方法中还有jc(num)方法,于是接下来调用jc(num)方法,因为jc方法递归直到1,所以调用顺序为:main--jc(5)--jc(4)--jc(3)--jc(2)--jc(1)。因为栈这种数据结构的特点是先进后出,所以方法的执行顺序是jc(1)--jc(2)--jc(3)--jc(4)--jc(5)然后返回给main方法。内存图如下:


  jc(1)是已知的值为1,所以将1 return 给jc(2),因为栈中调用特点为调用结束后被调用者就在栈中消失,所以这些方法会按jc(1)--jc(2)--jc(3)--jc(4)--jc(5)--main顺序依次return 回值并在栈中依次消失。

5、递归解决斐波那契数列。

  需求:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死, 问第二十个月的兔子对数为多少? 

  分析:因为每对兔子从第三个月开始每个月生一对小兔子,那么第一个月有1对;第二个月1对;第三个月2对;第四个月3对;第五个月5对。。。

  得到这样的一个数列:1,1,2,3,5,8,13,21。。。

  规律:从第三项开始,每一项是前两项之和。

  出口:出口一般都定义为已知的值,因为规律是从第三个月开始的,所以这里第一项和第二项是已知的。

  代码实现:

<span style="font-size:14px;">public class DiGuiDemo {
	public static void main(String[] args) {
		System.out.println(fun(20));
	}

        //定义递归方法
	public static int fun(int n) {
		 if (n == 1) {
		 return 1; //第一个月1对,返回1
		 } else if (n == 2) {
		 return 1; //第二个月1对,返回1
		 } else {
		 return fun(n - 1) + fun(n - 2); //从第三个月开始是前两个月对数之和
		 }
	}
}</span>

  小结:递归是方法调用方法本身的情况,利用递归可以解决一些能够将问题分解成小问题的情况。但是注意递归一定要有出口,并且递归次数不宜过多。

时间: 2024-11-03 08:05:41

递归解决斐波那契数列的相关文章

java数学归纳法非递归求斐波那契数列的方法_java

本文实例讲述了java数学归纳法非递归求斐波那契数列的方法.分享给大家供大家参考.具体如下: Integer能表示的最大值为 2147483647 大概是21.4亿,这里没有考虑溢出情况(当size为983时就会溢出)! import java.util.List; import java.util.ArrayList; /** * @author jxqlovejava * 斐波那契数列 */ public class Fibonacci { public static List<Intege

用PHP迭代器来实现一个斐波纳契数列

斐波纳契数列通常做法是用递归实现,当然还有其它的方法.这里现学现卖,用PHP的迭代器来实现一个斐波纳契数列,几乎没有什么难度,只是把类里的next()方法重写了一次.注释已经写到代码中,也是相当好理解的. <?php /* *@author nicesunboy@gmail.com */ class Fibonacci implements Iterator { private $previous = 1; private $current = 0; private $key = 0; publ

斐波那契数列和反向计算问题

反向计算:编写一个函数将一个整型转换为二进制形式 反向计算问题,递归比循环更简单 分析:需要理解,奇数的二进制最后一位是1,偶数的二进制最后一位一定是0,联想记忆,这个和整型的奇偶性是一致的,1本身就是奇数,0本身是偶数.     十进制整数转换为二进制整数采用"除2取余,逆序排列"法. 具体做法是:用2整除十进制整数,可以得到一个商和余数,再用2去除商,又会得到一个商和余数,如此进行,直到商为0时为止,然后把先得到的余数作为二进制数的低位有效位,后得到的余数作为二进制数的高位有效位,

Reverse反转算法+斐波那契数列递归+Reverse反转单链表算法--C++实现

Reverse反转算法 1 #include <iostream> 2 3 using namespace std; 4 //交换的函数 5 void replaced(int &a,int &b){ 6 int t = a; 7 a = b; 8 b = t; 9 } 10 //反转 11 void reversed(int a[],int length){ 12 int left = 0; 13 int right = length - 1; 14 while (left

递归-如何使用汇编 斐波那契数列 第N个数

问题描述 如何使用汇编 斐波那契数列 第N个数 要求使用递归方法 #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int n, r; if (argc < 2) { printf("Usage: %s number(<40)n", argv[0]); return -1; } n = atoi(argv[1]); __asm { // FILL YOU

递归形式与非递归形式的斐波那契数列的用法分析_C 语言

复制代码 代码如下: <SPAN style="FONT-SIZE: 32px">采用递归形式和非递归形式实现斐波那契数列</SPAN> 复制代码 代码如下: #include "stdafx.h"#include <iostream>using namespace std;//递归形式的斐波那契数列int fibonacciRecursion(int n){ if (n == 1 || n ==2) {  return 1; }

算法-斐波那契数列的性能优化

问题描述 斐波那契数列的性能优化 10C http://www.nowcoder.com/books/coding-interviews/c6c7742f5ba7442aada113136ddea0c3?rp=1 牛客网上 的这道题,一个简单的递归,性能不满足要求,请问 有什么提高性能的算法 解决方案 递归性能当然差了,解决档案是:将递归改为迭代! 解决方案二: 为啥不直接上通项公式 解决方案三: 这是我写的源代码.接下来我将对递归和迭代进行分析,我觉得这才是重点! 解决方案四: 在大部分情况下

斐波那契数列-Fibonacci数列 的疑问(一增一减的迭代法)

问题描述 Fibonacci数列 的疑问(一增一减的迭代法) 程序如下: int f = 0; int g = 1; for (int i = 0; i <= 15; i++) { println(f); f = f + g; g = f - g; } 输出:0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 问题1:为什么是用一增一减实现的? 问题2:还有关初值f和g是怎么设定的? 谢谢! 解决方案 public int fibonacci(int n){

打印菱形以及斐波纳契数列的几种解法介绍

1.编写程序,打印*菱形推出第i行要打印的空白个数及*号个数,用for循环依次打印各行 复制代码 代码如下: #include<stdio.h> //总共要打印2*n-1行,逐行打印 void print1(int n) { int i,j; for(i=1;i<=n;i++){//打印1至n行 for(j=1;j<=n-i;j++)//打印n-i个空格 printf(" "); for(j=1;j<=2*i-1;j++)//打印2*i-1个*号 prin