最简单的版本:每一项等于前两项之和,这个用递归或者循环就可以解决。
这里我们延伸出一个生活中兔子繁衍的实际案例:一开始有 A 只兔子,每只兔子 B 个月后可以生出 C 只小兔子,兔子在第 D
展示了A=1,B=2,C=2,D=3的情况下兔子繁衍过程
这里我们使用面向对象的思维解决😄
首先是建模:
第一个我们定义兔子窝,它有窝里兔子、兔子寿命、兔子繁殖年龄、兔子每次繁殖数量4个属性,还有增加兔子、移除兔子、获取N月后兔子数量3个行为。
第二个我们定义兔子,它有年龄1个属性,还有成长、繁殖、死亡3个行为。
1、兔子窝
先看代码
/**
* 兔子窝
*/
static class RabbitHome {
// 窝里兔子
private final List<Rabbit> rabbitList;
// 兔子寿命
private final int lifeSpan;
// 兔子繁殖年龄
private final int breedAge;
// 兔子每次繁殖数量
private final int everyBreedNum;
public RabbitHome(List<Rabbit> rabbitList, int lifeSpan, int breedAge, int everyBreedNum) {
this.rabbitList = rabbitList;
this.lifeSpan = lifeSpan;
this.breedAge = breedAge;
this.everyBreedNum = everyBreedNum;
}
/**
* 添加兔子
*
* @param rabbit 兔子
*/
public void addRabbit(Rabbit rabbit) {
rabbitList.add(rabbit);
}
/**
* 移除兔子
*
* @param rabbit 兔子
*/
public void removeRabbit(Rabbit rabbit) {
rabbitList.remove(rabbit);
}
/**
* 获取兔子数量
*
* @param months 第几个月
* @return 窝里兔子数量
*/
public int getRabbitCount(int months) {
if (months < 1) {
return rabbitList.size();
}
for (int i = 0; i < months; i++) {
for (Rabbit rabbit : rabbitList) {
// 成长
rabbit.grow();
// 繁殖
if (rabbit.age >= breedAge) {
rabbit.breed(this, everyBreedNum);
}
// 死亡
if (rabbit.age == lifeSpan) {
rabbit.die(this);
}
}
}
return rabbitList.size();
}
}
重点是获取兔子数量这个方法,需要模拟兔子每月之后的繁衍过程。
有了兔子窝,需要一个兔子窝工厂负责其创建过程。因为兔子繁衍需要迭代过程中对集合进行修改,所以使用CopyOnWriteArrayList。
/**
* 兔子窝工厂
*/
static class RabbitHomeFactory {
/**
* 创建兔子窝
*
* @param initialRabbitNum 开始兔子数量
* @param lifeSpan 寿命
* @param breedAge 繁殖年龄
* @param everyBreedNum 每次繁殖数量
* @return 兔子窝
*/
public static RabbitHome create(int initialRabbitNum, int lifeSpan, int breedAge, int everyBreedNum) {
if (initialRabbitNum < 1 || lifeSpan < 1 || breedAge < 1 || everyBreedNum < 1) {
throw new IllegalArgumentException("存在参数小于1");
}
List<Rabbit> rabbitList = new CopyOnWriteArrayList<>();
for (int i = 0; i < initialRabbitNum; i++) {
rabbitList.add(new Rabbit(0));
}
return new RabbitHome(rabbitList, lifeSpan, breedAge, everyBreedNum);
}
}
2、兔子
兔子的成长就是年龄加1,繁殖就是往兔子窝增加新的兔子,死亡就是从兔子窝移除自己。
/**
* 兔子
*/
static class Rabbit {
// 年龄
private int age;
public Rabbit(int age) {
this.age = age;
}
/**
* 成长
*/
public void grow() {
age++;
}
/**
* 繁殖
*
* @param rabbitHome 兔子窝
* @param everyBreedNum 每次繁殖数量
*/
public void breed(RabbitHome rabbitHome, int everyBreedNum) {
for (int i = 0; i < everyBreedNum; i++) {
rabbitHome.addRabbit(new Rabbit(0));
}
}
/**
* 死亡
*
* @param rabbitHome 兔子窝
*/
public void die(RabbitHome rabbitHome) {
rabbitHome.removeRabbit(this);
}
}
3、测试
就测试下开头图片那个过程吧
public static void main(String[] args) {
/*
* 第0个月存在兔子数量:1
* 第1个月存在兔子数量:1
* 第2个月存在兔子数量:3
* 第3个月存在兔子数量:4
* 第4个月存在兔子数量:8
* 第5个月存在兔子数量:14
* 第6个月存在兔子数量:24
*/
for (int i = 0; i <= 6; i++) {
RabbitHome rabbitHome = RabbitHomeFactory.create(1, 3, 2, 2);
System.out.println("第" + i + "个月存在兔子数量:" + rabbitHome.getRabbitCount(i));
}
}
结果如下
下面附上一个类装下的全部代码,当然实际别这么干🙂
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 斐波那契数列(兔子繁衍问题):
* 一开始有 A 只兔子,每只兔子 B 个月后可以生出 C 只小兔子,兔子在第 D 个月之后会死亡。
* 求第N个月兔子数量
*/
public class Fibonacci {
public static void main(String[] args) {
/*
* 第0个月存在兔子数量:1
* 第1个月存在兔子数量:1
* 第2个月存在兔子数量:3
* 第3个月存在兔子数量:4
* 第4个月存在兔子数量:8
* 第5个月存在兔子数量:14
* 第6个月存在兔子数量:24
*/
for (int i = 0; i <= 6; i++) {
RabbitHome rabbitHome = RabbitHomeFactory.create(1, 3, 2, 2);
System.out.println("第" + i + "个月存在兔子数量:" + rabbitHome.getRabbitCount(i));
}
}
/**
* 兔子窝
*/
static class RabbitHome {
// 窝里兔子
private final List<Rabbit> rabbitList;
// 兔子寿命
private final int lifeSpan;
// 兔子繁殖年龄
private final int breedAge;
// 兔子每次繁殖数量
private final int everyBreedNum;
public RabbitHome(List<Rabbit> rabbitList, int lifeSpan, int breedAge, int everyBreedNum) {
this.rabbitList = rabbitList;
this.lifeSpan = lifeSpan;
this.breedAge = breedAge;
this.everyBreedNum = everyBreedNum;
}
/**
* 添加兔子
*
* @param rabbit 兔子
*/
public void addRabbit(Rabbit rabbit) {
rabbitList.add(rabbit);
}
/**
* 移除兔子
*
* @param rabbit 兔子
*/
public void removeRabbit(Rabbit rabbit) {
rabbitList.remove(rabbit);
}
/**
* 获取兔子数量
*
* @param months 第几个月
* @return 窝里兔子数量
*/
public int getRabbitCount(int months) {
if (months < 1) {
return rabbitList.size();
}
for (int i = 0; i < months; i++) {
for (Rabbit rabbit : rabbitList) {
// 成长
rabbit.grow();
// 繁殖
if (rabbit.age >= breedAge) {
rabbit.breed(this, everyBreedNum);
}
// 死亡
if (rabbit.age == lifeSpan) {
rabbit.die(this);
}
}
}
return rabbitList.size();
}
}
/**
* 兔子窝工厂
*/
static class RabbitHomeFactory {
/**
* 创建兔子窝
*
* @param initialRabbitNum 开始兔子数量
* @param lifeSpan 寿命
* @param breedAge 繁殖年龄
* @param everyBreedNum 每次繁殖数量
* @return 兔子窝
*/
public static RabbitHome create(int initialRabbitNum, int lifeSpan, int breedAge, int everyBreedNum) {
if (initialRabbitNum < 1 || lifeSpan < 1 || breedAge < 1 || everyBreedNum < 1) {
throw new IllegalArgumentException("存在参数小于1");
}
List<Rabbit> rabbitList = new CopyOnWriteArrayList<>();
for (int i = 0; i < initialRabbitNum; i++) {
rabbitList.add(new Rabbit(0));
}
return new RabbitHome(rabbitList, lifeSpan, breedAge, everyBreedNum);
}
}
/**
* 兔子
*/
static class Rabbit {
// 年龄
private int age;
public Rabbit(int age) {
this.age = age;
}
/**
* 成长
*/
public void grow() {
age++;
}
/**
* 繁殖
*
* @param rabbitHome 兔子窝
* @param everyBreedNum 每次繁殖数量
*/
public void breed(RabbitHome rabbitHome, int everyBreedNum) {
for (int i = 0; i < everyBreedNum; i++) {
rabbitHome.addRabbit(new Rabbit(0));
}
}
/**
* 死亡
*
* @param rabbitHome 兔子窝
*/
public void die(RabbitHome rabbitHome) {
rabbitHome.removeRabbit(this);
}
}
}