×

开篇引子

前面三篇文章讲了数组(一维、二维、工具类、可变参数)和方法(定义、重载、递归、值传递),但光看不练等于白看。这篇就出 5 道综合练习题,难度循序渐进。

建议先别看答案,自己写一遍再对照。代码这东西,敲出来才算自己的。

练习 1:数组元素去重

题目:给定一个数组 {1, 3, 2, 1, 5, 3, 7, 2},写一个方法 distinct(int[] arr),返回去重后的新数组,不改变原数组。

思路:遍历原数组,用 boolean 标记是否已经出现过,将第一次出现的元素存入新数组。

import java.util.Arrays;

public class Exercise1 {
    public static void main(String[] args) {
        int[] arr = {1, 3, 2, 1, 5, 3, 7, 2};
        int[] result = distinct(arr);
        System.out.println("原数组:" + Arrays.toString(arr));
        System.out.println("去重后:" + Arrays.toString(result));
        // 期望:[1, 3, 2, 5, 7]
    }
    
    public static int[] distinct(int[] arr) {
        // 标记数组,记录元素是否已经出现过
        // 这里限制:数组元素 >= 0,最大不超过 int 范围
        // 更通用的做法是用 HashMap,但还没学到,先这样
        boolean[] seen = new boolean[1000];
        int count = 0;
        
        // 第一遍:统计不重复元素个数
        for (int num : arr) {
            if (!seen[num]) {
                seen[num] = true;
                count++;
            }
        }
        
        // 创建结果数组
        int[] result = new int[count];
        // 重置 seen,重新遍历收集
        seen = new boolean[1000];
        int index = 0;
        for (int num : arr) {
            if (!seen[num]) {
                seen[num] = true;
                result[index++] = num;
            }
        }
        
        return result;
    }
}

运行结果:[1, 3, 2, 5, 7]

考点:数组遍历、新数组创建、判断重复的逻辑思维。

练习 2:统计字符串中每个字符的出现次数

题目:写一个方法 countChars(String str),统计字符串中每个字符出现的次数,打印结果。不考虑中文字符。

思路:字符可以转换为 int(ASCII 码),用长度为 128(或 256)的数组计数。

public class Exercise2 {
    public static void main(String[] args) {
        countChars("hello world");
    }
    
    public static void countChars(String str) {
        // ASCII 码完整范围 0~127
        int[] counts = new int[128];
        
        // 遍历字符串,统计每个字符出现次数
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            counts[c]++;  // 字符作为下标,自动转 int
        }
        
        // 打印结果
        System.out.println("字符统计:");
        for (int i = 0; i < counts.length; i++) {
            if (counts[i] > 0) {
                System.out.println("  '" + (char) i + "' :" + counts[i] + " 次");
            }
        }
    }
}

运行结果:

字符统计:
  ' ' :1 次
  'd' :1 次
  'e' :1 次
  'h' :1 次
  'l' :3 次
  'o' :2 次
  'r' :1 次
  'w' :1 次

考点:字符与整型的转换、数组元素自增、String.charAt() 方法的使用。

这个技巧很实用——把字符当数组下标用的思路,在很多算法题里都会出现。

练习 3:方法重载——求多种形状的面积

题目:利用方法重载实现 area()——支持计算正方形、长方形、圆形的面积。

public class Exercise3 {
    public static void main(String[] args) {
        System.out.println("正方形边长 5:" + area(5));
        System.out.println("长方形 4×6:" + area(4, 6));
        System.out.println("圆形半径 3:" + area(3.0));
    }
    
    // 正方形面积
    public static int area(int side) {
        return side * side;
    }
    
    // 长方形面积
    public static int area(int length, int width) {
        return length * width;
    }
    
    // 圆形面积
    public static double area(double radius) {
        return Math.PI * radius * radius;
    }
}

运行结果:

正方形边长 5:25
长方形 4×6:24
圆形半径 3:28.274333882308138

考点:方法重载的三种形式——参数个数不同、参数类型不同、返回类型自动匹配。

注意第三个 area(3.0) 传的是 double,不会匹配到 area(int)。如果传 area(3),就会匹配第一个 int 版本。

练习 4:递归——十进制转二进制

题目:写一个递归方法 toBinary(int n),将十进制正整数转换为二进制字符串。

思路:除 2 取余法——不断除以 2,把余数拼起来。递归写法刚好对应”先求商再拼接余数”。

public class Exercise4 {
    public static void main(String[] args) {
        System.out.println("10 的二进制:" + toBinary(10));   // 1010
        System.out.println("42 的二进制:" + toBinary(42));   // 101010
        System.out.println("255 的二进制:" + toBinary(255)); // 11111111
    }
    
    public static String toBinary(int n) {
        // 终止条件
        if (n == 0) {
            return "0";
        }
        if (n == 1) {
            return "1";
        }
        // 递归步骤:先算 n/2 的二进制,再拼接 n%2
        return toBinary(n / 2) + (n % 2);
    }
}

执行过程(n=10):

toBinary(10)
→ toBinary(5) + "0"
→ toBinary(2) + "1" + "0"
→ toBinary(1) + "0" + "1" + "0"
→ "1" + "0" + "1" + "0"
→ "1010"

考点:递归的终止条件设置、递归结果拼接、数学知识(进制转换)与编程的结合。

练习 5:冒泡排序 + 二分查找

题目:给定数组 {24, 7, 43, 15, 9, 31, 18, 3},先排序再查找。实现:

  • bubbleSort(int[] arr) —— 冒泡排序(升序)
  • binarySearch(int[] arr, int target) —— 二分查找
  • main 方法测试:找 15 和 99 的位置
import java.util.Arrays;

public class Exercise5 {
    public static void main(String[] args) {
        int[] arr = {24, 7, 43, 15, 9, 31, 18, 3};
        
        System.out.println("排序前:" + Arrays.toString(arr));
        
        // 排序(冒泡排序会修改原数组,先复制一份)
        int[] sorted = Arrays.copyOf(arr, arr.length);
        bubbleSort(sorted);
        System.out.println("排序后:" + Arrays.toString(sorted));
        
        // 查找
        int target1 = 15;
        int index1 = binarySearch(sorted, target1);
        System.out.println(target1 + " 的位置:" + index1);
        
        int target2 = 99;
        int index2 = binarySearch(sorted, target2);
        System.out.println(target2 + " 的位置:" + index2 + "(-1 表示未找到)");
    }
    
    /**
     * 冒泡排序(升序)
     */
    public static void bubbleSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            boolean swapped = false;  // 优化:如果本轮没有交换,说明已经有序
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    swapped = true;
                }
            }
            if (!swapped) break;  // 提前结束
        }
    }
    
    /**
     * 二分查找(数组必须已排序)
     * @return 目标值的下标,未找到返回 -1
     */
    public static int binarySearch(int[] arr, int target) {
        int left = 0;
        int right = arr.length - 1;
        
        while (left <= right) {
            int mid = left + (right - left) / 2;  // 防止溢出
            
            if (arr[mid] == target) {
                return mid;
            } else if (arr[mid] < target) {
                left = mid + 1;      // 在右半部分
            } else {
                right = mid - 1;     // 在左半部分
            }
        }
        
        return -1;  // 未找到
    }
}

运行结果:

排序前:[24, 7, 43, 15, 9, 31, 18, 3]
排序后:[3, 7, 9, 15, 18, 24, 31, 43]
15 的位置:3
99 的位置:-1(-1 表示未找到)

考点:

  • 冒泡排序(含 swapped 优化)
  • 二分查找的 left/right 指针移动逻辑
  • mid = left + (right - left) / 2 避免 (left + right) / 2 可能溢出的问题
  • 方法封装——排序和查找各一个方法,各司其职
  • Arrays.copyOf() 保护原数组不被修改

总结

这 5 道题覆盖了数组与方法的核心场景:

  • 练习 1:数组遍历 + 去重逻辑(标记思想)
  • 练习 2:字符统计(字符当数组下标用的技巧)
  • 练习 3:方法重载的实际应用
  • 练习 4:递归实现进制转换
  • 练习 5:排序 + 查找的组合应用、方法封装

到此,数组与方法这个专题就结束了。下一篇我们进入 JavaSE 的重头戏——面向对象:类与对象、封装、继承、多态。那就是 Java 真正精彩的地方了。

加油,Java 路漫漫,代码敲起来 😎

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

作者

2248768396@qq.com

相关文章

08. 方法详解:定义、重载、递归与值传递

开篇引子——为什么要有方法? 我们的代码一直...

读出全部

06. 数组基础:一维数组、遍历与常见操作

开篇引子——为什么需要数组? 想象一下:你要...

读出全部