题目一:古典问题:有一对兔子,从出生后第 3 个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?
A.普通方法: 保证a一直小于b(当n>=3时)
1.核心代码
while(true){
if(n==1||n==2){
System.out.println("第"+n+"个月兔子总数为:"+sum+"对");
flag=true;
}else if(n>=3){
//相加次数为n-2次
for (int i =n-2; i>0; i--) {
//保证每次a都会小于b
sum=a+b;
a=b;
b=sum;
//测试语句:System.out.println("a的值为:"+a+",b的值为:"+b);
}
System.out.println("第"+n+"个月兔子总数为:"+sum+"对");
flag=true;
}else{
flag=false;
System.out.println("输入n的值有误,请检查后重新输入");
System.out.println("请再次输入n的值");
n=scanner.nextInt();
}
if(flag){
break;
}
}
2.常见问题点分析
2.1 如何保证每次a<b(当n>=3)???
解决方案: 建立一个sum变量用来接收每月的兔子总数,
每次接收完后,b会把原来的b值传给a
然后b就就接收sum的值
2.2 布尔类型变量flag的作用是什么???
解答:flag默认初始值为true
a.当输入的n不符合条件时,flag值变为false
此时无法使用break关键字跳出循环
随后界面提示重新输入n的值
b.当输入的n符合条件时,flag值不变
得到兔子总数sum后
可以使用break跳出循环
c.对于a情况,再次输入一个正确的n值
会得到兔子总数且跳出循环
2.3 内层循环次数(相加次数)为多少???
解答如下所示:
当n=3,1+1=2,需要相加1次
当n=4时 1+1=2,1+2=3;需要相加2次
当n=5时 1+1=2,1+2=3,2+3=5;需要相加3次
因而需要相加次数=n-2
3.运行截图
3.1 首次输入有误且n=1
3.2 首次输入有误且n=2
3.3 首次输入有误且n=5
3.4 首次输入正确且n=8
4.源代码
import java.util.Scanner;
public class TestRabbit01 {
public static void main(String[] args) {
System.out.println("题目:古典问题:有一对兔子,从出生后第 3 个月起每个月都生一对兔子\n小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问n个月的兔子总数为多少?");
//前提条件: 第一个月时,兔子总数为1对,第二个月时,兔子总数为1对
int a=1,b=1;
System.out.println("请输入n的值:");
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
boolean flag=true;
//用来判断是否跳出循环,默认为true
// 当n输入有误时,flag=false,此时不会跳出循环
int sum=1;
//保存每月兔子总数
while(true){
if(n==1||n==2){
flag=true;
System.out.println("第"+n+"个月兔子总数为:"+sum+"对");
}else if(n>=3){
//相加次数为n-2次
for (int i =n-2; i>0; i--) {
//保证每次a都会小于b
sum=a+b;
a=b;
b=sum;
//System.out.println("a的值为:"+a+",b的值为:"+b);
}
flag=true;
System.out.println("第"+n+"个月兔子总数为:"+sum+"对");
}else{
flag=false;
System.out.println("输入n的值有误,请检查后重新输入");
System.out.println("请再次输入n的值");
n=scanner.nextInt();
}
if(flag){
break;
}
}
}
}
B.递归法: f(n)=f(n-1)+f(n-2)(n>3)
1.核心代码
public static int Sum(int N){
//如果输入的月份为第一个月或第二个月
//那兔子的总数就为1
if(N==1||N==2){
return 1;
}
//当N>=3时,就会执行递归方法,方法内进行方法的调用
return Sum(N-1)+Sum(N-2);
}
2.常见问题点分析
2.1 如何保证第一个月和第二个月的兔子总数为1???
解决方案: 在函数Sum里面对接收过来的值N进行判断
若N值为1或者N值为2时,函数的返回值为1
2.2 f(N)=f(N-1)+f(N-2)(n>=3)的由来???
解答如下所示:
当N=3时,f(3)=1+1=f(1)+f(2)=2
当N=4时f(4)=1+2=f(2)+f(3)=3
当N=5时f(5)=2+3=f(3)+f(4)=5
…
因而f(N)=f(N-2)+f(N-1)=f(N-1)+f(N-2)
2.3 布尔类型变量flag的作用是什么???
解答如下所示:
1.当n不符合条件时,flag=false,需要重新输入n的值
然后进行下一轮的n值判断,
若结果还是不符合,就重新执行上述操作
(重新输入n且进行判断)
2.当n符合条件时,flag=true,
得到兔子总数后会跳出循环
3.运行截图
3.1 首次输入有误且n=1
3.2 首次输入有误且n=2
3.3 首次输入有误且n=4
3.4 首次输入正确且n=6
4.源代码
import java.util.Scanner;
public class TestRabbit02 {
public static void main(String[] args) {
System.out.println("题目:古典问题:有一对兔子,从出生后第 3 个月起每个月都生一对兔子\n小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问n个月的兔子总数为多少?");
//前提条件: 第一个月时,兔子总数为1对,第二个月时,兔子总数为1对
System.out.println("请输入n的值:");
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
boolean flag=true;
int sum=0;
//定义sum变量用来存放兔子的总数
while(true){
if(n<1){
//此时不满足跳出循环条件,flag值应为false
flag=false;
System.out.println("输入的n值(第几个月)有误,请检查后重新输入");
System.out.println("请再次输入n的值");
n=scanner.nextInt();
}else{
sum=Sum(n);
//保证非首次输入正确的n值时,程序也能正确执行
flag=true;
//符合条件,跳出循环
if (flag) {
break;
}
}
}
System.out.println("第"+n+"个月兔子总数为:"+sum+"对");
}
public static int Sum(int N){
//如果输入的月份为第一个月或第二个月
//那兔子的总数就为1
if(N==1||N==2){
return 1;
}
return Sum(N-1)+Sum(N-2);
}
}