兔子生兔子问题


关于兔子生兔子的算法详解


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

 

分析:

第1个月  --  1对

第2个月  --  1对

第3个月 -- 原来的1对 +  新生1对  =  2对

第4个月 --前面存在的3对(即第3个月的数量) +  往后2个月的兔子对生的兔子 1对(即4  - 2  = 2月的兔子对生的兔子对 1对) = 2 + 1 =  3对

第5个月  --第4个月的兔子对数量 (3对) +  第3个月兔子对所生的兔子对(2对,因为兔子出生2个月后可以生兔子) =  3  +  2  = 5 

第6个月 --第5个月的兔子对数量 (5对) +  第4个月兔子对所生的兔子对(3对) = 5 + 3 = 8

以此类推

兔子的规律为数列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...

 

所以很明显兔子数量为斐波那契数列,下面只需要用代码计算斐波那契数列即可。 

   public static int feibo(int num){
   		if ( (num == 1) || (num == 2))	{
               	return 1 ;
		}else{
			return feibo(num - 1) + feibo(num - 2) ;
		}


 

        }

以下为完整java程序:

public class FeiboTest {
	 public static void main(String []args){
		int num = Integer.valueOf(args[0]) ; //通过命令参数传入月份 java FeiboTest 10
 		System.out.println(feibo(num)) ;
        
        }

        public static int feibo(int num){
    		if ( (num) == 1 || (num == 2))	{
                	return 1 ;
 		}else{
			return feibo(num - 1) + feibo(num - 2) ;
		}
        }

}


 

 

其实这种重复问题使用递归,会有很大的浪费,比如,计算feibo(8) =feibo(7) + feibo(6)

而feibo(7) 的计算也会用到feibo(6) ,而这个feibo(6) 每次又是通过递归重新计算的。 
我们可以先做一个测试: 

      
 
public static int feibo(int num) {
		System.out.println("feibo(" + num + ") 被调用.");
		if ((num == 1) || (num == 2)) {
			return 1;
		} else {
			return feibo(num - 1) + feibo(num - 2);
		}
	}

你调用一下fibo(10),就会发现,好多的函数被重复调用了

	所以,我们要想更好的办法避免这些浪费,这就用到了“动态规划”的思想: 

	private static int ARRS[] = new int[50];定义一个数组(这里为了说明问题,考虑50个月以内的) 

	这样,第一次调用后,把这个值存在数组中,(feibo(i)的值保存在a[i-1]中) 

	这样下一次,在使用这个值的时候就可以直接调用而不是递归了。 

	新的动态规划版斐波那契函数: 


public class FeiboTest {
	private static int ARRS[] = new int[50] ;
	static {
		for (int i = 0; i< 100; i++){
			ARRS[i] = 0 ;
		}
	}

	public static void main(String[] args) {
		int num = Integer.valueOf(args[0]);
		System.out.println(feibo(num));
		for (int i = 0; i < 100; i++) {
			if  (ARRS[i] == 0) {
				break ;
			}
			System.out.println("+++++++ " + ARRS[i]);
		}

	}

	public static int feibo(int num) {
		if (ARRS[num-1] != 0){
			return ARRS[num -1] ;
		}else{
			if ((num == 1) || (num == 2)) {
				ARRS[num -1] = 1;
				return 1;
			} else {
				ARRS[num -1] = feibo(num - 1) + feibo(num - 2);
			    return ARRS[num -1] ;	
			}
		}
	}
}



  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值