AP Computer Science A 数组 — 完整学习指南
适用对象:备考 AP Computer Science A 的中国学生。
本章覆盖:数组声明、实例化、默认值、下标(0 起)、标准
for与增强for-each遍历、常用算法(求和、最值、计数、查找、反转)、数组作参数 — AP CS A Unit 6。前置知识:迭代(Unit 4)、写类(Unit 5)。
关于练习题的说明:下文练习题均为我们按 AP CS A 风格原创的教学题。
1. 为什么数组重要
Unit 6 高分值 — 占 AP CS A 10-15%,且数组是 Unit 7(ArrayList)和 Unit 8(二维数组)的基础。多数 FRQ Q3 与 Q4 重数组。
两个核心:
- 数组是固定长度、按下标索引的同类型数据集合。
- 数组是引用类型 — 变量持有指针,不直接持有内容。
2. 声明与实例化
int[] a; // 声明引用(当前为 null)
a = new int[5]; // 实例化长度 5 的数组(默认值全 0)
int[] b = {3, 1, 4, 1, 5}; // 一行:声明 + 实例化 + 初始化
String[] words = new String[3]; // String 数组(默认值全 null)
数组长度分配后固定。要「扩容」必须分配新数组并复制。
默认值:int、double → 0 / 0.0;boolean → false;String 等引用类型 → null。
3. 下标(0 起)
int[] a = {3, 1, 4, 1, 5};
a[0]; // 3
a[4]; // 5
a[5]; // 运行时 ArrayIndexOutOfBoundsException
a.length; // 5 — 注意:**无括号**(字段,非方法)
最后一个有效下标永远是 a.length - 1。AP 评分常抓偏一错误。
可读可写:a[2] = 99; 更新第三个元素。
4. 标准 for 遍历
int[] nums = {3, 1, 4, 1, 5};
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
}
// sum = 14
需要下标时用(如比较相邻元素、写入数组)。条件是 i < nums.length,不是 <=。
5. 增强 for-each 循环
int[] nums = {3, 1, 4, 1, 5};
int sum = 0;
for (int n : nums) {
sum += n;
}
// sum = 14
读法:「对 nums 中每个 n」。只需值时更简洁。不能用增强 for 来:
- 修改数组(
n = 99只改本地副本n)。 - 取下标(需要
i时用标准for)。 - 反向迭代或跳元素。
6. 常用算法
求最大:
int max = a[0];
for (int i = 1; i < a.length; i++) {
if (a[i] > max) max = a[i];
}
线性查找:
int target = 4;
int found = -1;
for (int i = 0; i < a.length; i++) {
if (a[i] == target) { found = i; break; }
}
原地反转(双指针):
for (int i = 0; i < a.length / 2; i++) {
int tmp = a[i];
a[i] = a[a.length - 1 - i];
a[a.length - 1 - i] = tmp;
}
计数:
int count = 0;
for (int n : a) {
if (n == target) count++;
}
7. 数组作参数与返回值
public static int sum(int[] a) {
int total = 0;
for (int n : a) total += n;
return total;
}
public static int[] doubleAll(int[] a) {
int[] result = new int[a.length];
for (int i = 0; i < a.length; i++) result[i] = 2 * a[i];
return result;
}
把数组传给方法时,方法收到的是同一数组的引用 — 方法内修改元素外部可见。(但把参数重新指向新数组不影响调用者 — 只有改内容才影响。)
8. 例题精讲
写方法 mostFrequent(int[] arr),返回出现最多的元素。若并列,返回较小的那个。
解答。
public static int mostFrequent(int[] arr) {
int bestVal = arr[0];
int bestCount = 0;
for (int i = 0; i < arr.length; i++) {
int count = 0;
for (int j = 0; j < arr.length; j++) {
if (arr[j] == arr[i]) count++;
}
if (count > bestCount || (count == bestCount && arr[i] < bestVal)) {
bestCount = count;
bestVal = arr[i];
}
}
return bestVal;
}
对每个 arr[i],内层循环数它出现次数,超过当前最佳(或相等但更小)时更新。 — AP 规模够用。
对输入 {3, 1, 4, 1, 5, 1, 4, 4}:3→1、1→3、4→3、5→1。1 与 4 并列 3 次 → 返回最小者 1。
9. 易错点
lengthvslength():数组用a.length(字段)。字符串用s.length()(方法)。CED 常考这个区别。- 偏一:条件是
i < a.length,不是i <= a.length。最后有效下标a.length - 1。 - 增强 for 中修改:
for (int n : a) n = 99;不改数组 —n是副本。 - 忘记
new:int[] a;声明但未实例化。在a = new int[5];前用a[0]抛NullPointerException。 - 别名:
int[] b = a;让b与a指向同一数组。要复制用Arrays.copyOf(a, a.length)。
10. 练习题(CED 风格)
- 写方法
boolean isSorted(int[] a)判断a是否非递减。 - 写方法
int[] removeDuplicates(int[] a)返回去掉相邻重复后的新数组(如 {1,1,2,3,3,3,4} → {1,2,3,4})。 - 给
int[] a = {5, 3, 8, 1, 4},不用排序步骤,把最大与最小元素交换位置。
11. 速查表
- 声明:
int[] a = new int[10];或int[] a = {1,2,3}; - 下标 0 起:最后下标
a.length - 1。 - 长度:
a.length(无括号)。 - for 循环:
for (int i = 0; i < a.length; i++)— 用下标访问。 - for-each:
for (int n : a)— 仅读值。 - 默认值:int=0、double=0.0、boolean=false、引用=null。
- 引用传递:方法看到同一数组。
- 越界:
a[a.length]抛ArrayIndexOutOfBoundsException。
12. 下一步
数组是 Unit 7(ArrayList) 的基础 — 可变长度、更多方法。Unit 8(二维数组) 推广到网格/矩阵。手写数组算法是 FRQ Q3 必备能力。具体算法可问小欧:「如何 O(n) 找第二大?」或「帮我跟踪这道嵌套循环数组题。」