题目:一条鱼每个月都可以生产10条小鱼,小鱼3个月后才可以生产,问如果一开始有1条鱼,那么1年内一共会有多少条鱼?
如果直接用java代码实现会比较容易,首先写一个Fish类:
package sang;
import java.util.ArrayList;
import java.util.List;
public class Fish {
// 出生月份
private int bornMonth;
// 能否生鱼
private boolean canProduce = false;
// 生鱼数量
private int amount = 10;
public Fish() {
}
public Fish(int amount) {
this.amount = amount;
}
public Fish(int bornMonth, boolean canProduce) {
this.bornMonth = bornMonth;
this.canProduce = canProduce;
}
public int getBornMonth() {
return bornMonth;
}
public void setBornMonth(int bornMonth) {
this.bornMonth = bornMonth;
}
public boolean isCanProduce() {
return canProduce;
}
public void setCanProduce(boolean canProduce) {
this.canProduce = canProduce;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
//生产小鱼
public List<Fish> produce(int bornMonth) {
List<Fish> fishes = new ArrayList<Fish>(amount);
for (int i = 0; i < amount; i++) {
Fish f = new Fish();
f.setBornMonth(bornMonth);
f.setCanProduce(false);
fishes.add(f);
}
return fishes;
}
}
再写一个测试类,该类中有一个count方法如下:
/*
保存数量
static int count = 0;
生鱼周期
int cycle = 3;
12个月
int year = 12;
*/
public long count(Fish mother) {
//保存鱼
List<Fish> sons = new ArrayList<Fish>();
// 保存数量
long result = 0;
Fish fish = null;
// 队列中的索引
int index = 0;
//循环1年之内
for (int currentMonth = 1; currentMonth <= year; currentMonth++) {
index = 0;
// 母鱼每个月都生产
// 加入到队列中
sons.addAll(mother.produce(currentMonth));
while (index < sons.size()) {
// 从队列中取鱼
fish = sons.get(index);
if (fish != null) {
// 是否能生产
if (fish.isCanProduce()
|| ((currentMonth - fish.getBornMonth()) >= this.cycle)) {
fish.setCanProduce(true);
// 将此鱼生产的小鱼加入到队列中
sons.addAll(fish.produce(currentMonth));
}
index++;
}
}
}
result = sons.size();
return result;
}
该方法能够计算出一年内一共会有多少条鱼,该方法中用ArrayList来保存鱼对象,最后计算出长度可得鱼的数量。但是实际的数量会特别大,所以会很占用内存,甚至会出现内存溢出的情况,如果你是2GB的内存,则amount设置为10个鱼可以运行,但如果20、50或100的情况下会OutOfMemoryError,所以该方法不现实,但是这样做思路却很清晰。那么根据上述代码即可产生如下计算:
假设1月份开始有一条鱼,那么它可以生产m条小鱼,小鱼过3个月后,也就是4月份才可以生产,那么1月份到3月份的鱼的个数分别为m、m、m。到4月份的时候,1月份生产的小鱼开始生产,每个鱼生产m条,那么4月份鱼的总数为m+m*m。所以5月份的时候鱼的总数为m+2(m*m)(加上了4月份生产的小鱼),6月份的时候鱼的总数为m+3(m*m)(加上了5月份生产的小鱼),以此类推...
按此种方法计算,实现的代码为:
public long count2(int amount) {
//生产数量
int m = amount;
//计算公式
int[] f = new int[] { m, m, m };
int x = m;
//前3个月
long result = 3 * m;
int k = 0;
//从第4个月开始
for (int i = 4; i <= 12; i++) {
if (k < cycle) {
x = x + m * f[k];
result += x;
f[k] = x;
k++;
} else {
k = 0;
i--;
}
}
return result;
}
由于不再保存Fish对象仅根据上述分析公式计算结果,
只要结果不超出long的范围就不会有异常。该方法很简单,就是根据上述分析写出。
测试一下:
amount=10的时候,结果为:210620
amount=20的时候,结果为:2866240
amount=100的时候,结果为:1556451200
如果用第一种方法呢?
amount=10的时候,结果为:210620
amount=20的时候,结果为:Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
最后说一下,此文章本人原创,也是没事的时候想到的题目就写了一下,希望大家指点!