# 2026-07-15 数组进阶练习(课堂练习用) > **说明**:以下题目为数组的进阶应用,作为课堂练习或学有余力的同学额外挑战使用。 --- ### 练习 1:数组元素首尾交换 **难度**:⭐⭐ **知识点**:数组索引操作、变量交换 定义一个整数数组 `{10, 20, 30, 40, 50}`,将数组中第 1 个元素与第 5 个元素交换,第 2 个元素与第 4 个元素交换(即首尾对称交换),然后输出交换后的数组。 **示例输出**: ``` 交换前:10 20 30 40 50 交换后:50 40 30 20 10 ``` > **提示**:可以用变量交换的经典三步法 `temp = a; a = b; b = temp;`。 **参考代码**: ```java /** * @title 练习1:数组元素首尾交换 * @create 2026/7/15 */ public class Practice01 { public static void main(String[] args) { int[] arr = {10, 20, 30, 40, 50}; // 输出交换前的数组 System.out.print("交换前:"); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } System.out.println(); // 首尾对称交换:第1位↔第5位,第2位↔第4位 // 即 arr[0]↔arr[4], arr[1]↔arr[3] int temp = arr[0]; arr[0] = arr[4]; arr[4] = temp; temp = arr[1]; arr[1] = arr[3]; arr[3] = temp; // 输出交换后的数组 System.out.print("交换后:"); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } System.out.println(); } } ``` ---### 练习 2:数组元素循环右移 **难度**:⭐⭐⭐ **知识点**:数组操作、循环、下标运算 定义一个整数数组 `{1, 2, 3, 4, 5}`,将数组中的所有元素向右移动 2 个位置。超出数组范围的元素循环移到数组开头(循环右移)。 **示例**: ``` 移动前:1 2 3 4 5 右移2位:4 5 1 2 3 ``` **要求**: - 在原数组上操作,不创建新数组 - 移动位数用一个变量 `k = 2` 控制 - 思考:如果 k 大于数组长度怎么办?(提示:`k = k % 数组长度`) **参考代码**: ```java /** * @title 练习2:数组元素循环右移 * @create 2026/7/15 */ public class Practice02 { public static void main(String[] args) { int[] arr = {1, 2, 3, 4, 5}; int k = 2; // 右移位数 // 如果 k 大于数组长度,取模简化 k = k % arr.length; // 输出移动前的数组 System.out.print("移动前:"); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } System.out.println(); // 整体右移 k 位(循环右移) for (int i = 0; i < k; i++) { // 保存最后一个元素 int last = arr[arr.length - 1]; // 从后往前,每个元素往后移一位 for (int j = arr.length - 1; j > 0; j--) { arr[j] = arr[j - 1]; } // 把最后一个元素放到第一位 arr[0] = last; } // 输出移动后的数组 System.out.print("右移" + k + "位后:"); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } System.out.println(); } } ``` --- ### 练习 3:数组去重 **难度**:⭐⭐⭐ **知识点**:数组遍历、嵌套循环、if 判断、新数组 定义一个整数数组 `{5, 2, 8, 2, 5, 9, 1, 8, 3}`,去除数组中重复的元素,只保留第一次出现的元素,输出去重后的新数组。 **要求**: - 不能使用 `Set` 等集合类 - 只能使用数组和循环实现 - 去重后的元素顺序保持原顺序 **示例输出**: ``` 原数组: 5 2 8 2 5 9 1 8 3 去重后: 5 2 8 9 1 3 ``` **提示**: - 可以先统计不重复元素的个数,再创建新数组 - 或者创建一个足够大的新数组,遍历原数组判断是否已存在 **参考代码**: ```java /** * @title 练习3:数组去重 * @create 2026/7/15 */ public class Practice03 { public static void main(String[] args) { int[] arr = {5, 2, 8, 2, 5, 9, 1, 8, 3}; // 输出原数组 System.out.print("原数组:"); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } System.out.println(); // 第一步:统计不重复元素的个数 int count = 0; // 不重复元素的个数 for (int i = 0; i < arr.length; i++) { boolean isRepeat = false; // 检查 arr[i] 在它之前是否出现过 for (int j = 0; j < i; j++) { if (arr[i] == arr[j]) { isRepeat = true; break; } } if (!isRepeat) { count++; // 不重复,计数+1 } } // 第二步:创建新数组,存放不重复的元素 int[] newArr = new int[count]; int index = 0; // 新数组的当前索引 for (int i = 0; i < arr.length; i++) { boolean isRepeat = false; // 检查 arr[i] 是否已放入新数组 for (int j = 0; j < i; j++) { if (arr[i] == arr[j]) { isRepeat = true; break; } } if (!isRepeat) { newArr[index] = arr[i]; index++; } } // 输出去重后的数组 System.out.print("去重后:"); for (int i = 0; i < newArr.length; i++) { System.out.print(newArr[i] + " "); } System.out.println(); } } ``` --- ### 练习 4:双色球号码生成器 **难度**:⭐⭐⭐⭐ **知识点**:数组、随机数、嵌套循环、去重 模拟双色球彩票号码生成: **规则**: 1. 红球:从 1~33 中随机选出 **6 个不重复** 的号码 2. 蓝球:从 1~16 中随机选出 **1 个** 号码 **要求**: - 红球号码存入一个 int 数组 - 蓝球号码单独用一个 int 变量存储 - 红球号码不能重复(每次生成新号码时,需要检查是否已存在) **示例输出**: ``` 红球号码:05 12 18 23 27 31 蓝球号码:09 ``` **提示**: ```java // 生成 1~33 之间的随机整数 int num = (int)(Math.random() * 33) + 1; ``` **参考代码**: ```java /** * @title 练习4:双色球号码生成器 * @create 2026/7/15 */ public class Practice04 { public static void main(String[] args) { int[] redBalls = new int[6]; // 红球数组,6个号码 int blueBall; // 蓝球号码 // 生成红球号码(6个不重复的 1~33) int index = 0; // 已生成的红球个数 while (index < 6) { // 生成一个候选号码 int num = (int)(Math.random() * 33) + 1; // 检查是否已存在(去重) boolean isRepeat = false; for (int i = 0; i < index; i++) { if (redBalls[i] == num) { isRepeat = true; break; } } // 不重复则加入数组 if (!isRepeat) { redBalls[index] = num; index++; } } // 生成蓝球号码(1个 1~16) blueBall = (int)(Math.random() * 16) + 1; // 输出结果 System.out.print("红球号码:"); for (int i = 0; i < redBalls.length; i++) { // 个位数补0输出,如 05 if (redBalls[i] < 10) { System.out.print("0"); } System.out.print(redBalls[i] + " "); } System.out.println(); System.out.print("蓝球号码:"); if (blueBall < 10) { System.out.print("0"); } System.out.println(blueBall); } } ``` ---### 练习 5:基本类型 vs 引用类型(代码分析) **难度**:⭐⭐ **知识点**:基本数据类型 vs 引用数据类型 ```java public class ThinkDemo { public static void main(String[] args) { int a = 10; int b = a; b = 20; System.out.println("a = " + a); // ? System.out.println("b = " + b); // ? int[] arr1 = {1, 2, 3}; int[] arr2 = arr1; arr2[0] = 999; System.out.println("arr1[0] = " + arr1[0]); // ? System.out.println("arr2[0] = " + arr2[0]); // ? } } ``` 请问以上代码的运行结果是什么?为什么 `arr1[0]` 的值会被改变?结合课堂笔记中"基本数据类型 vs 引用数据类型"的知识,在注释中写出你的分析。 **参考代码**: ```java /** * @title 练习5:基本类型 vs 引用类型 * @create 2026/7/15 */ public class Practice05 { public static void main(String[] args) { /* 问题分析: ① int a = 10; int b = a; 基本数据类型赋值,b 复制了 a 的值 10,两者独立。 之后 b = 20,只改变 b,a 不受影响。 所以 a = 10,b = 20。 ② int[] arr1 = {1, 2, 3}; int[] arr2 = arr1; 引用数据类型赋值,arr2 复制的是 arr1 的地址值, 两者指向堆内存中的同一个数组对象。 所以 arr2[0] = 999 修改的是它们共同指向的数组, arr1[0] 自然也跟着变成了 999。 结论: 基本数据类型存的是"值"本身,赋值时各玩各的。 引用数据类型存的是"地址值",赋值时多个引用指向同一块内存。 */ // ===== 基本数据类型测试 ===== int a = 10; int b = a; // b 复制 a 的值 b = 20; // 只改变 b System.out.println("a = " + a); // 10(a 不受影响) System.out.println("b = " + b); // 20 // ===== 引用数据类型测试 ===== int[] arr1 = {1, 2, 3}; int[] arr2 = arr1; // arr2 复制 arr1 的地址值 arr2[0] = 999; // 通过 arr2 修改数组 System.out.println("arr1[0] = " + arr1[0]); // 999(arr1 也变了!) System.out.println("arr2[0] = " + arr2[0]); // 999 } } ``` --- > **参考笔记**:[20260715-笔记.md](../课堂笔记/01-JavaSE基础-笔记/20260715-笔记.md) 第三章「数组(Array)」