费式数列有关问题
费式数列问题
古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?
程序中的bearAge为3时,即为题目中的3个月,也可以为任意大于等于2个月后生。
package algorithm.fibonacci; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class RabbitService { class Rabbit { public int age; public Rabbit() { this.age = 1; } public Rabbit(int age) { this.age = age; } } /* * 面向对象方法 */ public void printRabbit(int month, int bearAge) { if (month > 0) { long start = System.currentTimeMillis(); // 保存每个月份的兔子数目 long[] rabbitNumbersArray = new long[month]; // rabbitList保存所有的兔子,在第一个月有一对大兔子 Rabbit bigRabbit = new Rabbit(); List<Rabbit> rabbitList = new ArrayList<Rabbit>(); rabbitList.add(bigRabbit); rabbitNumbersArray[0] = rabbitList.size(); // 从第二个月开始计算,如果兔子刚生下来age为1,则age为3时兔子才能生兔子 for (int currentMonth = 2; currentMonth <= month; currentMonth++) { int lastMonthRabbitNumber = rabbitList.size(); for (int i = 0; i < lastMonthRabbitNumber; i++) { Rabbit rabbit = rabbitList.get(i); rabbit.age++; if (rabbit.age >= bearAge) { rabbitList.add(new Rabbit()); } } rabbitNumbersArray[currentMonth - 1] = rabbitList.size(); } long end = System.currentTimeMillis(); System.out.println("1月到" + month + "月的兔子数目为:" + Arrays.toString(rabbitNumbersArray) + ",使用时间为" + (end - start)); } else { System.out.println("输入月份必须大于0"); } } /* * 作用递归方法计算费式数列,当兔子生育月不为3时,也可以计算 */ public void printRabbit2(int month, int bearAge) { if (month > 0) { long start = System.currentTimeMillis(); long[] rabbitNumbersArray = new long[month]; for (int i = 1; i <= month; i++) { rabbitNumbersArray[i - 1] = fibonacci(i, bearAge); } long end = System.currentTimeMillis(); System.out.println("1月到" + month + "月的兔子数目为:" + Arrays.toString(rabbitNumbersArray) + ",使用时间为" + (end - start)); } else { System.out.println("输入月份必须大于0"); } } private int fibonacci(int n, int bearAge) { if (n < bearAge) { return 1; } else { return fibonacci(n - 1, bearAge) + fibonacci(n - (bearAge - 1), bearAge); } } /* * 根据费式数列特点,当前值为前两项之和 */ public void printRabbit3(int month, int bearAge) { if (month > 0) { long start = System.currentTimeMillis(); long[] rabbitNumbersArray = new long[month]; int currentMonth = 0; for (currentMonth = 1; currentMonth < bearAge; currentMonth++) { rabbitNumbersArray[currentMonth - 1] = 1; } for (currentMonth = bearAge; currentMonth <= month; currentMonth++) { rabbitNumbersArray[currentMonth - 1] = rabbitNumbersArray[currentMonth - bearAge] + rabbitNumbersArray[currentMonth - 2]; } long end = System.currentTimeMillis(); System.out.println("1月到" + month + "月的兔子数目为:" + Arrays.toString(rabbitNumbersArray) + ",使用时间为" + (end - start)); } else { System.out.println("输入月份必须大于0"); } } public static void main(String[] args) { RabbitService service = new RabbitService(); int bearAge = 3; service.printRabbit(20, bearAge); service.printRabbit2(20, bearAge); service.printRabbit3(20, bearAge); } }
输出:
1月到20月的兔子数目为:[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765],使用时间为6 1月到20月的兔子数目为:[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765],使用时间为2 1月到20月的兔子数目为:[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765],使用时间为0