- 0
- 405 words
开篇引子
前面三篇文章讲了数组(一维、二维、工具类、可变参数)和方法(定义、重载、递归、值传递),但光看不练等于白看。这篇就出 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 路漫漫,代码敲起来 😎