09综合算法练习题

目录

1. 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?(斐波那契)(递归)

方法一:递归

方法二:循环

2. 判断101-200之间有多少个素数,并输出所有素数

方法一:内层循换判断素数

方法二:外层循环判断素数

方法三:优化方法二

3. 打印出所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数字本身。例如:153是一个水仙花数,因为153 = 13+53+33。

4. (递归)将一个正整数分解质因数。例如:输入90,打印出90= 2* 3 * 3 *5。

方法一:循环

方法二:循环内递归

5. 利用条件运算符的嵌套来完成此题:学习成绩 >= 90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示

6. 输入两个正整数m和n,求其最大公约数和最小公倍数

正则表达式,增强for,字符串转数组)7.输入一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数

方法一:字符比较

方法二:ASCII码比较

方法三:正则表达式

知识小结

重点理解

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四个数字,能组成多少个互不相同且一个数字中无重复数字的三位?并把它们都输出

(double精度出现问题)12.企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可可提成7.5%;20万到40万之间时,高于20万元的部分,可提成5%;40万到60万之间时高于40万元的部分,可提成3%;60万到100万之间时,高于60万元的部分,可提成1.5%,高于100万元时,超过100万元的部分按1%提成,从键盘输入当月利润,求应发放奖金总数?

(发现%n为换行)13. 一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?

14. 输入某年某月某日,判断这一天是这一年的第几天?

方法一 :每个月分类计算当前月之前的月经过的天数

方法二:优化方法一,优化switch写法。将大月,小月,2月。分成三类,用循环自动累加天数即可。

15. 输入三个整数x,y,z,请把这三个数由小到大输出

16. 输出9*9口诀

17. 猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个 第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。求第一天共摘了多少

18. 两个乒乓球队进行比赛,各出三人。甲队为a,b,c三人,乙队为x,y,z三人。已抽签决定比赛名单。有人向队员打听比赛的名单。a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单。

(增加字符串长度)19. 打印出如下图案菱形

方法二:分为上下两部分输出字符串或数组打印

方法三:分为上下两部分按数量输出字符和空格

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为止。当前除数就为两数的最大公约数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodingW丨编程之路

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值