递归的Fibonacci在数羊
一、由数羊引起的
有一道经典的面试题是这样的。
题目:一头母羊的寿命是5年,它会在第2年底和第4年底各生下一头母羊,第5年底死去,
问一开始农场有1头母羊,N年后,农场会有多少只母羊?
(假设没有公羊也会生羊,而且只只生母羊,不要较真 - -!)
乍一看不知所云,其实慢慢分析so easy!
思路:
年数 羊的个数 备注
1 1 1只羊
2 2=1+1 生1只
3 2 不生
4 4=2+2 第1只在第4年生,第2只在第2年生
5 3=4-1 第1只样死去
6 6=3+3 第2只在4年生,第3只在第2年生,第4只在第2年生
7 5=6-1 第2只样死去
8 10=5+5 第3只在第4年生,第4只在第4年生,
9 8=10-2 第3只和第4只死去
10 16=8+8 继续生...
规律:奇数年是1 2 3 5 8 的斐波那契数列
偶数年是2 4 6 10 16的斐波那契数列
所以我们首先得了解Fibonacci数列。
二、Fibonacci数列
【题目】一列数的规则如下: 1、1、2、3、5、8、13、21、34...... 求第30位数是多少, 用递归算法实现。
/// <summary> /// 一列数的规则如下: 1、1、2、3、5、8、13、21、34...... 求第30位数是多少, 用递归算法实现 /// </summary> /// <param name="pos">第几位</param> /// <returns>返回该位置处的数字</returns> public int Fib(int pos) { if (pos <= 0) { return 0; } if (pos == 1) { return 1; } int result = Fib(pos - 1) + Fib(pos - 2); return result; }
我们还可以将递归改为非递归。利用数组就可实现。比方说:
/// <summary> /// 非递归算法计算斐波那契数,速度要比递归快 /// </summary> /// <param name="pos">第几位</param> /// <returns>返回该位置处的数字</returns> public int GetNumAtPos(int pos) { int result = 0; int[] arr = new int[1000 * 1000]; arr[0] = 1; arr[1] = 1; for (int i = 2; i < pos; i++) { arr[i] = arr[i - 2] + arr[i - 1]; } result = arr[pos - 1]; return result; }
三、农场养羊问题
了解了Fibonacci数列之后,我们继续回到数羊的问题上。根据分析的思路可以写出如下一种实现方式:
public class Fibonacci { /// <summary> /// 题目:一头母羊的寿命是5年,它会在第2年底和第4年底各生下一头母羊,第5年底死去, /// 问一开始农场有1头母羊,N年后,农场会有多少只母羊?(假设只生母羊,不要较真 - -!) /// </summary> /// <remarks> /// 思路: ///年数 羊的个数 备注 ///1 1 1只羊 ///2 2=1+1 生1只 ///3 2 不生 ///4 4=2+2 第1只在第4年生,第2只在第2年生 ///5 3=4-1 第1只样死去 ///6 6=3+3 第2只在4年生,第3只在第2年生,第4只在第2年生 ///7 5=6-1 第2只样死去 ///8 10=5+5 第3只在第4年生,第4只在第4年生, ///9 8=10-2 第3只和第4只死去 ///10 16=8+8 继续生... ///规律:奇数年是1 2 3 5 8 的斐波那契数列 /// 偶数年是2 4 6 10 16的斐波那契数列 /// </remarks> /// <param name="year"></param> /// <returns></returns> public int CountSheep(int year) { int result = 0; // 奇数年 if (year%2==1) { year = (year + 1) / 2; // 折半 result = EvenSum(year); return result; } // 偶数年 if (year%2==0) { year = year / 2; // 折半 result = OddSum(year); return result; } return result; } /// <summary> /// 奇数年的Fibonacci数 /// </summary> /// <param name="year">第几年</param> /// <returns>羊的个数</returns> private int EvenSum(int year) { int num = 0; if (year <= 0) { return 0; } if (year==1) { return 1; } if (year==2) { return 2; } num = EvenSum(year - 1) + EvenSum(year - 2); return num; } /// <summary> /// 偶数年的Fibonacci数 /// </summary> /// <param name="year">第几年</param> /// <returns>羊的个数</returns> private int OddSum(int year) { int num = 0; if (year<=0) { return 0; } if (year==1) { return 2; } if (year==2) { return 4; } num = OddSum(year - 1) + OddSum(year - 2); return num; } }
测试方法如下:
static void Main(string[] args) { int result = 0; // 斐波那契方法测试 Fibonacci fib = new Fibonacci(); //result = fib.Fib(30); // 非递归数组方法测试 //result = fib.GetNumAtPos(50); // 数羊测试 for (int i = 1; i <= 12; i++) { result = fib.CountSheep(i); Console.WriteLine("第 " + i + " 年羊的个数为:" + result); } Console.ReadLine(); }
运行效果如下:
作者:樊勇
出处:http://www.cnblogs.com/fanyong/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
我的联系方式:fanyong@gmail.com
个人独立博客:www.fy98.com