一、由数羊引起的
有一道经典的面试题是这样的。
题目:一头母羊的寿命是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();
}
运行效果如下: