目录
1. 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?(斐波那契)(递归)
3. 打印出所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数字本身。例如:153是一个水仙花数,因为153 = 13+53+33。
4. (递归)将一个正整数分解质因数。例如:输入90,打印出90= 2* 3 * 3 *5。
5. 利用条件运算符的嵌套来完成此题:学习成绩 >= 90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示
正则表达式,增强for,字符串转数组)7.输入一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数
8. 求s = a+aa+aaa+aaaa+aa……a的值,其中a是一个数字。例如2+22+222+2222+22222(此时共有5个数相加),几个数相加由键盘控制
9. 一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如6 = 1+2+3.编程找出1000以内的所有完数
10. 一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在第10次落地时,共经过多少米?第 10次反弹多高?
11. 有1,2,3,4四个数字,能组成多少个互不相同且一个数字中无重复数字的三位?并把它们都输出
(发现%n为换行)13. 一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?
方法二:优化方法一,优化switch写法。将大月,小月,2月。分成三类,用循环自动累加天数即可。
18. 两个乒乓球队进行比赛,各出三人。甲队为a,b,c三人,乙队为x,y,z三人。已抽签决定比赛名单。有人向队员打听比赛的名单。a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单。
20. 有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13…求出这个数列的前20项之和
1. 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?(斐波那契)(递归)
思路:
①手动写前几个月兔子的总数,因为兔子需要成长需要第三个月才能生崽,所以计算当月兔子对数
时,发现是上一个月的兔子数(基础兔子数)+上上个月的兔子对数=本月新生的兔子对数(因为
上上个月的兔子正好这个月开始生,并且是一对生一对)
②单位为对。1,1,2,3,5, 8,13,21 从这些数字来看,发现其规律就是从第3个数字开始,每个
数字的值等于前面紧邻的两个数字的和,所以这是一个斐波那契数列。
斐波那契数列最常规的做法是递归。
方法一:递归
//1.第一想法是用递归,要区分每个月生下来的兔子和计算每个月可生育的兔子数目
//1.2递归写法
public class Test {
//第一想法是用递归,要区分每个月生下来的兔子和计算每个月可生育的兔子数目
public static int rabbit(int i ){
//每次进行一次方法都是一个月
//排除月份输入错误的情况
if(i<1){
return -1;
}
//前三个月第一对兔子无法生育
if(i<3){
return 1;
}
return (rabbit(i-1)+rabbit(i-2));
}
}
改进,将i换为month
递归能不用就不用因为
1)造成大量的资源浪费
2)可能会造成栈溢出异常
方法二:循环
用两个变量来表示所求月份的前两个月的数量,然后不断迭代更新这两个月份的值,再相加这两个
月份的值,就能求出该月份的兔子数量。
//1.1循环写法,更优
public static int rabbit_1(int month){
if(month<1){
return -1;
}
//前三个月第一对兔子无法生育
int temp = 0;//中间变量
int num1 = 1;
int num2 = 1;
for(int k = 3;k<= month;k++){
temp = num2;
num2 = temp +num1;
num1 = temp;
}
return num2;
}
调用测试部分及结果
public static void main(String[] args){
//1.
//1.
System.out.println("第8个月的兔子总数为"+rabbit(8)+"对");
System.out.println("第6个月的兔子总数为"+rabbit(6)+"对");
System.out.println("第23个月的兔子总数为"+rabbit(23)+"对");
System.out.println("第8个月的兔子总数为"+rabbit_1(8)+"对");
System.out.println("第6个月的兔子总数为"+rabbit_1(6)+"对");
System.out.println("第23个月的兔子总数为"+rabbit_1(23)+"对");
}
2. 判断101-200之间有多少个素数,并输出所有素数
思路:
① 素数又称质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。
简单理解就是,质数只可以被1和他自身整除。
② 通过外层循环,来循环数字101-200。
③ 通过内层循环从101开始检查,让101除以2,3,4……100。同理,判断199时除以2,3,4……
198。判断中途是否有整除,如果有则不是素数,则无需进行下一次循环,跳出。
工具:开方的sqrt()方法
方法一:内层循换判断素数
设置一个boolean类型变量,初始值为真,如果中途有数整除则设置为假
//2.3内层循换判断素数。更差写法,在每个数字已经判断不是素数后依旧会进行循环
public static void prime_1(int num1 ,int num2){
int i = 0,j = 0;
for( i = num1;i<=num2;i++){
boolean sign = true;//每个数字循环开始除数时,都默认为素数。不能受上一个数字影响
for(j = 2;j<i;j++){
if( i%j == 0){
//判断是否为素数的条件在内层循环
sign = false;//中间有进入这一层的判断,说明有整除的情况,设置不是素数
}
}
if(sign == true){//筛选后的都是素数,打印
System.out.print(" "+i+",");
}
}
System.out.println();
}
方法二:外层循环判断素数
当除数从2开始逐渐加到被除数-1的情况下判断,若中间都没有整除导致的跳出,除数会一直加到
最后一次与被除数相同才因为不满足循环体判断条件跳出,而不是内部的判断。跳出后在外层循环
//2.101-200的素数
public static void prime(int num1,int num2){//查找素数的范围
int i = 0,j = 0;
for( i = num1;i<= num2;i++){
for( j = 2; j<i; j++ ){
if(i%j == 0){
break;
}
}
if( j == i){
//说明没有中途跳出
System.out.print(" "+i+",");
}
}
}
方法三:优化方法二
优化方法二,将其除数的取值范围从[2,被除数-1]换为[2,被除数开方]
思路:因为如果一个数不是素数是合数, 那么一定可以由两个自然数相乘得到, 其中一个大于或等于
它的平方根,一个小于或等于它的平方根,并且成对出现。
参考的作者原写法 int k = (int)Math.sqrt((double)i+1);难理解的点,关于开方时,i为什么+1
public static void prime_2(int num1,int num2){//查找素数的范围
int i = 0,j = 0;
for( i = num1;i<= num2;i++){
int k = (int)Math.sqrt(i);
//System.out.print(" "+k);
for( j = 2; j<=k; j++ ){
if(i%j == 0){
break;
}
}
//判断是否为素数的条件在外层循环
if( j == k+1){
//说明没有中途跳出
System.out.print(" "+i+",");
}
}
System.out.println();
}
调试结果
prime(101,200);
prime_1(101,200);
prime_2(101,200);
3. 打印出所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数字本身。例如:153是一个水仙花数,因为153 = 13+53+33。
思路:
① 循环遍历所有三位数
循环体内
② 通过取余,除十取余,来取出三位数的个位,十位,百位。
③ 进行立方加计算判断
工具:%,/
// 3.打印所有水仙花数
public static void narcissus(){
int bits = 0,ten = 0,hun = 0;
for(int i = 100;i<=999;i++){
bits = i %10;
ten = (i/10)%10;
hun = i/100;
if(bits*bits*bits + ten*ten*ten + hun*hun*hun == i){
System.out.print(i+" ");
}
}
}
narcissus();
4. (递归)将一个正整数分解质因数。例如:输入90,打印出90= 2* 3 * 3 *5。
思路:
1>①保证是质因数的原理是,从最小的质数2开始除该正整数,若成功整除,输出除数记录。再将
商当做新的被除数分解,依旧从最小的2重新开始。
②注意除数不是只除一次,除到有余数为止,除数才自增(例如90 = 223*5,2需要参与两次)
2>①用递归,每次用循环的数成功整除以后,都证明新找到一个因数。输出因数
②然后将除后的商作为新的形参调用递归,再进行分解因数,依次类推。
方法一:循环
//4.分解质因数
//4.1循环写法
public static void decompose(int num){
System.out.print(num+"=");
for(int temp = 2;temp<= num;){//为了满足在同一个temp下多分解几次的情况,自增条件留白
if( num%temp == 0){
if(num/temp == 1){
//走到最后一个质因数的情况,去掉末尾的*
System.out.print(temp);
break;
}
else{
//当前除数一直可以整除被除数,不自增。只一直使用当前除数分解被除数
System.out.print(temp+"*");
num = num/temp;//为了提取已经找到的因子,分解大项。这一步可以改写为递归
}
}
else{
temp++;//当前的除数temp已经不能整除被除数,自增
}
}
}
方法二:循环内递归
//4.2递归写法
/**
* 加深理解
* @param num
*/
public static void decompose_1(int num){
for(int temp = 2; temp<=num; temp++){
if(num%temp == 0){
if( num/temp == 1){
//末尾情况,结束方法
System.out.print(temp);
return;
}else{
//整除成功,打印记录
System.out.print(temp+"*");
decompose_1(num/temp);//递归时,分解新的num,从除数2开始
break;//进入下一层递归返回后无需再进行循环。
}
}
//一直找不到可以整除的除数,除数自增。num是质数的情况,temp自增到和num相同进入结束判断,停止
}
}
decompose(126);
decompose(90);
decompose(97);
decompose_1(90);
decompose_1(89);
5. 利用条件运算符的嵌套来完成此题:学习成绩 >= 90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示
public static void grade(int num){
if(num < 90){
if(num<60){
System.out.println("该同学的成绩为C");
}
else{
System.out.println("该同学的成绩为B");
}
}
else{
System.out.println("该同学的成绩为A");
}
}
grade(90);
grade(89);
grade(61);
grade(60);
grade(57);
6. 输入两个正整数m和n,求其最大公约数和最小公倍数
思路:
① 最大公约数,指两个或多个整数共有约数中最大的一个。
② 这里使用辗转相除法, 又名欧几里德算法(Euclidean algorithm),是求最大公约数的一种方
法。
它的具体做法是:用较大数除以较小数,再用出现的余数(第一余数)去除除数,再用出现的余数
(第二余数)去除第一余数,如此反复,直到最后余数是0为止。当前除数就为两数的最大公约数