大学生必学练习题 - Java 语言经典50例

258 阅读3分钟

这是我参与更文挑战的第10天,活动详情查看: 更文挑战

本文正在参加「Java主题月 - Java 开发实战」,详情查看 活动链接

我是陈皮,一个在互联网 Coding 的 ITer,微信搜索「陈皮的JavaLib」第一时间阅读最新文章,回复【资料】,即可获得我精心整理的技术资料,电子书籍,一线大厂面试资料和优秀简历模板。

引言

在大学期间,Java 语言一般会作为计算机专业类的课程,而且也不少学生会选择 Java 来作为学习编程的主要语言。在学习掌握基础知识之后,通过大量的编程练习题,手写代码,是巩固基础知识,锻炼编程思维的重要手段之一。下面介绍 Java 语言练习实例50例,题目+解题思路 + 解法。

1 汉诺塔

题目:假设一块板上有三根针 A、B、C。A 针上套有 64 个大小不等的圆盘,按照大的在下、小的在上的顺序排列,要把这 64 个圆盘从 A 针移动到 C 针上,每次只能移动一个圆盘,移动过程可以借助 B 针。但在任何时候,任何针上的圆盘都必须保持大盘在下,小盘在上。从键盘输入需移动的圆盘个数,给出移动的过程。

分析:利用递归实现圆盘的整个移动过程;当只移动一个圆盘时,直接将圆盘从 A 针移动到 C 针。若移动的圆盘为 n(n>1),则分成几步走:把 (n-1) 个圆盘从 A 针移动到 B 针(借助 C 针);A 针上的最后一个圆盘移动到 C 针;B 针上的 (n-1) 个圆盘移动到 C 针(借助 A 针)。每做一遍,移动的圆盘少一个,逐次递减,最后当 n 为 1 时,完成整个移动过程。

package com.nobody;

/**
 * @Description
 * @Author Mr.nobody
 * @Date 2021/5/31
 * @Version 1.0
 */
public class Demo {
    public static void main(String[] args) {
        // 将3个盘子从A移动到C
        hanoi(3, 'A', 'B', 'C');
    }

    /**
     * 汉诺塔转移过程
     * 
     * @param n 盘子数量
     * @param from 起点柱子
     * @param inter 中转柱子
     * @param to 终点柱子
     */
    public static void hanoi(int n, char from, char inter, char to) {
        // 只剩一个盘子的时候直接从from移动到to
        if (n == 1) {
            System.out.println("盘子1从 " + from + " 移动到 " + to);
        } else {
            // 将最上面的n-1个盘子从起点借助终点移动到中转柱子
            hanoi(n - 1, from, to, inter);
            // 将当前最大的盘子直接从起点移动终点
            System.out.println("盘子" + n + "从 " + from + " 移动到 " + to);
            // 再将刚才n-1个盘子从中转点借助起点移动到终点
            hanoi(n - 1, inter, from, to);
        }
    }
}

演示代码的输出结果如下:

盘子1从 A 移动到 C
盘子2从 A 移动到 B
盘子1从 C 移动到 B
盘子3从 A 移动到 C
盘子1从 B 移动到 A
盘子2从 B 移动到 C
盘子1从 A 移动到 C

2 斐波那契数列

题目:斐波那契数列的第1项是0,第2项是1,第3项开始,每一项的值都是前两项之和。例如第3项是第1项和第2项之和,即 0+1=1,第4项是第2项和第3项之和,即 1+1=2。它是这样一个数列 0,1,1,2,3,5,8,13,21,......

分析:因为前2项比较特殊,所以单独处理,从第3项开始,通过前两项之和来求出下一项的值即可。有2种解法实现,一种解法是通过2个变量,不断保存前两项的值,然后求它们之和即可。另一种解法是通过递归算法,从当前项开始,不断递归求算前两项的值,直到第1项和第2项的值,即可回推。

package com.nobody;

/**
 * @Description 递归解法
 * @Author Mr.nobody
 * @Date 2021/5/31
 * @Version 1.0
 */
public class Demo {
    public static void main(String[] args) {
        // 输出前20个数
        int num = 20;
        for (int i = 1; i <= num; i++) {
            System.out.println("斐波那契数列第" + i + "项是" + fibonacci(i));
        }
    }

    public static long fibonacci(long number) {
        // 第1项和第2项特殊处理,即返回0和1
        if (number == 1 || number == 2) {
            return number - 1;
        } else {
            // 排除第1项和第2项,都是前两项的和
            return fibonacci(number - 2) + fibonacci(number - 1);
        }
    }
}
package com.nobody;

/**
 * @Description 非递归解法
 * @Author Mr.nobody
 * @Date 2021/5/31
 * @Version 1.0
 */
public class Demo {
    public static void main(String[] args) {
        // 输出前20个数
        int num = 20;
        // 保存前两项的值
        int x = 0, y = 1;
        // 当前项的值
        int curData;
        for (int i = 1; i <= num; i++) {
            // 第1项和第2项特殊处理,即返回0和1
            if (i == 1 || i == 2) {
                System.out.println("斐波那契数列第" + i + "项是" + (i - 1));
            } else { // 排除第1项和第2项,都是前两项的和
                curData = x + y;
                System.out.println("斐波那契数列第" + i + "项是" + curData);
                x = y;
                y = curData;
            }
        }
    }
}

演示代码的输出结果如下:

斐波那契数列第1项是0
斐波那契数列第2项是1
斐波那契数列第3项是1
斐波那契数列第4项是2
斐波那契数列第5项是3
斐波那契数列第6项是5
斐波那契数列第7项是8
斐波那契数列第8项是13
斐波那契数列第9项是21
斐波那契数列第10项是34
斐波那契数列第11项是55
斐波那契数列第12项是89
斐波那契数列第13项是144
斐波那契数列第14项是233
斐波那契数列第15项是377
斐波那契数列第16项是610
斐波那契数列第17项是987
斐波那契数列第18项是1597
斐波那契数列第19项是2584
斐波那契数列第20项是4181

3 九九乘法表

题目:输出九九乘法表。

分析:使用两层 for 循环遍历输出九九乘法表。

package com.nobody;

/**
 * @Description 九九乘法表
 * @Author Mr.nobody
 * @Date 2021/5/31
 * @Version 1.0
 */
public class Demo {
    public static void main(String[] args) {
        for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= i; j++) {
                System.out.print(j + "×" + i + "=" + i * j + "\t");
            }
            System.out.println();
        }
    }
}

演示代码的输出结果如下:

1×1=1	
1×2=2	2×2=4	
1×3=3	2×3=6	3×3=9	
1×4=4	2×4=8	3×4=12	4×4=16	
1×5=5	2×5=10	3×5=15	4×5=20	5×5=25	
1×6=6	2×6=12	3×6=18	4×6=24	5×6=30	6×6=36	
1×7=7	2×7=14	3×7=21	4×7=28	5×7=35	6×7=42	7×7=49	
1×8=8	2×8=16	3×8=24	4×8=32	5×8=40	6×8=48	7×8=56	8×8=64	
1×9=9	2×9=18	3×9=27	4×9=36	5×9=45	6×9=54	7×9=63	8×9=72	9×9=81

4 字符串替换

题目:将字符串的某一子串替换为另外的字符串。例如将 陈皮的JavaLibJava 子串替换为 C ,则最终变为 陈皮的CLib

分析:Java 类库中有许多实用的类,定义了许多通用的方法,可以使用 String 类的 replace 方法。

package com.nobody;

/**
 * @Description
 * @Author Mr.nobody
 * @Date 2021/5/31
 * @Version 1.0
 */
public class Demo {
    public static void main(String[] args) {
        String str = "我是陈皮,我的公众号【陈皮的JavaLib】";
        System.out.println("全部替换`陈皮`为`狗蛋`之后的字符串:" + str.replace("陈皮", "狗蛋"));
        System.out.println("全部替换`陈皮`为`狗蛋`之后的字符串:" + str.replaceAll("陈皮", "狗蛋"));
        System.out.println("只替换一个`陈皮`为`狗蛋`之后的字符串:" + str.replaceFirst("陈皮", "狗蛋"));
    }
}

演示代码的输出结果如下:

全部替换`陈皮`为`狗蛋`之后的字符串:我是狗蛋,我的公众号【狗蛋的JavaLib】
全部替换`陈皮`为`狗蛋`之后的字符串:我是狗蛋,我的公众号【狗蛋的JavaLib】
只替换一个`陈皮`为`狗蛋`之后的字符串:我是狗蛋,我的公众号【陈皮的JavaLib】

5 字符串反转

题目:将字符串反转,例如 abcde 反转为 edcba

分析:直接调用 StringBuffer 类的 reverse 方法。

package com.nobody;

/**
 * @Description
 * @Author Mr.nobody
 * @Date 2021/5/31
 * @Version 1.0
 */
public class Demo {
    public static void main(String[] args) {
        String str = "abcde";
        String reverse = new StringBuffer(str).reverse().toString();
        System.out.println(str + "反转后:" + reverse);
    }
}

演示代码的输出结果如下:

abcde反转后:edcba

6 打印倒立的三角形

题目:打印倒立的三角形,使用 * 号来打印。

分析:倒立的三角形,我们使用一行行往下打印的方法,注意的是每打印一行的时候,需要计算每一行前面需要打印多少个空格。

package com.nobody;

/**
 * @Description 打印倒立的三角形
 * @Author Mr.nobody
 * @Date 2021/5/31
 * @Version 1.0
 */
public class Demo {
    public static void main(String[] args) {
        // 打印6行的倒立的三角形
        for (int i = 1; i <= 6; i++) {
            // 打印每一行前的空格,下一行总会比上一行多一个空格
            for (int j = 0; j <= i; j++) {
                System.out.print(" ");
            }
            // 打印*
            for (int k = 1; k <= 11 - 2 * (i - 1); k++) {
                System.out.print("*");
            }
            System.out.println();
        }
    }
}

演示代码的输出结果如下:

  ***********
   *********
    *******
     *****
      ***
       *

7 解析 URL

题目:url 地址是有几部分组成的,例如协议,IP,端口,文件名等。请从 URL 中提取出来。

分析:通过 URL 类,里面定义了许多方法,分别用于提取 URL 中相应的信息。

package com.nobody;

import java.net.URL;

/**
 * @Description 解析 URL
 * @Date 2021/5/31
 * @Version 1.0
 */
public class Demo {
    public static void main(String[] args) throws Exception {
        URL url = new URL("http://www.nobody.com/html/index.html");
        System.out.println("URL:" + url.toString());
        System.out.println("协议:" + url.getProtocol());
        System.out.println("主机:" + url.getHost());
        System.out.println("端口号:" + url.getPort());
        System.out.println("文件名:" + url.getFile());
        System.out.println("路径:" + url.getPath());
        System.out.println("默认端口号:" + url.getDefaultPort());
    }
}

演示代码的输出结果如下:

URL:http://www.nobody.com/html/index.html
协议:http
主机:www.nobody.com
端口号:-1
文件名:/html/index.html
路径:/html/index.html
默认端口号:80

8 水仙花数

题目:水仙花数 是指一个三位数,其各位数字立方和等于该数本身。例如:153是一个水仙花数,153 = 1^3 + 5^3 + 3^3.

分析:遍历100-999 之间的数,计算每位数字的立方是否等于其本身。

package com.nobody;

/**
 * @Description 水仙花数
 * @Date 2021/5/31
 * @Version 1.0
 */
public class Demo {
    public static void main(String[] args) {
        int x, y, z;
        for (int i = 100; i <= 999; i++) {
            x = i % 10;
            y = i / 10 % 10;
            z = i / 100 % 10;

            if (i == (x * x * x + y * y * y + z * z * z)) {
                System.out.println(i);
            }
        }
    }
}

演示代码的输出结果如下:

153
370
371
407

9 杨辉三角

题目:杨辉三角的两个腰边的数都是 1,其它位置的数都是上顶上两个数之和。

package com.nobody;

/**
 * @Description 杨辉三角
 * @Date 2021/5/31
 * @Version 1.0
 */
public class Demo {
    public static void main(String[] args) {
        // 要打印的行数
        int n = 10;

        int i, j, k;

        int[][] a = new int[n + 1][n + 1];

        System.out.println(n + "行杨辉三角如下:");

        for (i = 1; i <= n; i++) {
            // 两边的数令它为1
            a[i][1] = a[i][i] = 1;
        }

        for (i = 3; i <= n; i++) {
            for (j = 2; j <= i - 1; j++) {
                // 除两边的数外都等于上两顶数之和
                a[i][j] = a[i - 1][j - 1] + a[i - 1][j];
            }
        }

        for (i = 1; i <= n; i++) {
            for (k = 1; k <= n - i; k++) {
                // 让显示美观,在输出数之前打上合适的空格
                System.out.print("   ");
            }
            for (j = 1; j <= i; j++) {
                System.out.printf("%6d", a[i][j]);
            }
            // 当一行数字输出后换行
            System.out.println();
        }
    }
}

演示代码的输出结果如下:

10行杨辉三角如下:
                                1
                             1     1
                          1     2     1
                       1     3     3     1
                    1     4     6     4     1
                 1     5    10    10     5     1
              1     6    15    20    15     6     1
           1     7    21    35    35    21     7     1
        1     8    28    56    70    56    28     8     1
     1     9    36    84   126   126    84    36     9     1

10 分解质因数

题目:将一个正整数分解质因数。例如:输入80,打印出 80 = 2 * 2 * 2 * 2 * 5。

分析:因为最小的质因数是2,所以从2开始递增遍历,最大不超过整数的一半。没找到一个质因数,则除去这个质因数,再继续遍历。

package com.nobody;

import java.util.Scanner;

/**
 * @Description 分解质因数
 * @Date 2021/5/31
 * @Version 1.0
 */
public class Demo {
    public static void main(String[] args) {
        System.out.print("请输入需要分解因数的整数:");
        Scanner scanner = new Scanner(System.in);
        int num = scanner.nextInt();

        // 分解质因数
        System.out.print(num + "分解质因数:");
        int tmp = num / 2;
        for (int i = 2; i <= tmp; i++) {
            if (num % i == 0) {
                num = num / i;
                System.out.print(i + " ");
                i = 1;
            }
        }
    }
}

演示代码的输出结果如下:

请输入需要分解因数的整数:80
80分解质因数:2 2 2 2 5 

11 小球自由下落

题目:一球从100米高度自由落下,每次落地后反跳回原高度的一半,再落下,求它在第10次落地时,共经过多少米?第10次反弹多高?

分析:第一次是从100米高处落下,这个经过的路径需要单独处理,即第一次落到地上时,经过100米了,此时高度是0米。然后再根据每次小球再弹上再回来,则每次来回经过的路程即是上弹的高度2倍。

package com.nobody;

/**
 * @Description 小球自由下落
 * @Date 2021/5/31
 * @Version 1.0
 */
public class Demo {
    public static void main(String[] args) {
        float h = 100, s = 100;
        // 第一次反弹高度
        h = h / 2;
        for (int i = 2; i <= 10; i++) {
            s = s + 2 * h;
            h = h / 2;
        }
        System.out.printf("第10次落地时,共经过%f米,第10次反弹高%f米", s, h);
    }
}

演示代码的输出结果如下:

第10次落地时,共经过299.609375米,第10次反弹高0.097656米

12 判断闰年

题目:闰年就是可以被4整除不能被100整除,或者可以被400整除,那么这一年就是闰年。

分析:判断年份是否可以被4整除不能被100整除,或者是否可以被400整除,如果两个条件有一个成立,那么这一年就是闰年。

package com.nobody;

import java.util.Scanner;

/**
 * @Description 判断闰年
 * @Date 2021/5/31
 * @Version 1.0
 */
public class Demo {
    public static void main(String[] args) {
        System.out.print("请输入年份:");
        Scanner sc = new Scanner(System.in);
        int year = sc.nextInt();

        // 判断年份是否可以被4整除但不能被100整除
        boolean isLeapYear = (year % 4 == 0) && (year % 100 != 0);
        // 判断年份是否能够被400整除
        boolean isLeapYear1 = year % 400 == 0;

        // 两个条件满足一个即是闰年
        if (isLeapYear || isLeapYear1) {
            System.out.println(year + "是闰年!");
        } else {
            System.out.println(year + "不是闰年!");
        }
    }
}

演示代码的输出结果如下:

请输入年份:2021
2021不是闰年!

请输入年份:2020
2020是闰年!

13 阶乘

题目:一个正整数的阶乘是所有小于及等于该数的正整数的积,0的阶乘为1。自然数n的阶乘写作n!,n!=1×2×3×...×n。

分析:计算一个数n的阶乘,其实就是等于n-1这个数的阶乘再乘于n,所以可以利用递归实现。

package com.nobody;

import java.util.Scanner;

/**
 * @Description 阶乘
 * @Date 2021/5/31
 * @Version 1.0
 */
public class Demo {
    public static void main(String[] args) {
        System.out.print("请输入一个整数:");
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        for (int i = 0; i <= n; i++) {
            System.out.printf("%d! = %d\n", i, factorial(i));
        }
    }

    public static long factorial(long n) {
        if (n <= 1) {
            return 1;
        } else {
            return n * factorial(n - 1);
        }
    }
}

演示代码的输出结果如下:

请输入一个整数:10
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800

持续更新,关注收藏持续学习 Java 语言练习题...