Unit 2: Selection
and Iteration
单元 2:选择
与循环
Decision-making with conditionals, repetition with loops, Boolean logic, De Morgan's Law, and essential standard algorithms.
用条件语句做决策、用循环做重复、布尔逻辑、德摩根定律,以及必会的标准算法。
Algorithms with Selection and Repetition
含选择与重复的算法
Algorithms are built from three fundamental blocks:
算法(algorithm)由三个基本结构构成:
Sequencing, steps execute in order, one at a time.
Selection, a choice is made based on a true/false decision.
Repetition, a process repeats until a desired outcome is reached.
顺序:各步骤依次执行,每次执行一条。
选择:根据 true/false 判断做出分支。
重复:某段过程不断重复,直到达成目标。
Boolean Expressions
布尔表达式
Relational Operators
关系运算符(relational operator)
| Operator | Meaning | Example | Result |
|---|---|---|---|
== | Equal to | 5 == 5 | true |
!= | Not equal to | 5 != 3 | true |
< | Less than | 3 < 5 | true |
> | Greater than | 3 > 5 | false |
<= | Less than or equal | 5 <= 5 | true |
>= | Greater than or equal | 6 >= 5 | true |
| 运算符 | 含义 | 示例 | 结果 |
|---|---|---|---|
== | 等于 | 5 == 5 | true |
!= | 不等于 | 5 != 3 | true |
< | 小于 | 3 < 5 | true |
> | 大于 | 3 > 5 | false |
<= | 小于等于 | 5 <= 5 | true |
>= | 大于等于 | 6 >= 5 | true |
== compares values. For objects (reference types), == compares references (memory addresses), not content. Use .equals() to compare object content.
== 比较值。对对象(object,引用类型),== 比较的是引用(内存地址),不是内容。要比较对象内容请用 .equals()。
int a = 10; boolean result = (a >= 5); // true// true
if Statements
if 语句
Selection statements alter the sequential flow of execution based on a Boolean condition.
选择语句根据布尔条件改变顺序执行的流程。
One-Way Selection (if)
单分支选择(if)
if (score >= 90) { System.out.println("Excellent!"); } // Body runs ONLY if condition is true// 仅当条件为 true 时循环体才执行
Two-Way Selection (if-else)
双分支选择(if-else)
if (age >= 18) { System.out.println("Adult"); } else { System.out.println("Minor"); }
if-else, exactly one branch always executes, never both, never neither.
if-else 中,必定恰好执行一个分支,不会两个都执行,也不会两个都跳过。
x = 7?if (x > 10) print("A"); else print("B");x = 7 时输出什么?if (x > 10) print("A"); else print("B");Nested if Statements
嵌套 if(nested if)语句
An if inside another if. The inner condition is only checked if the outer condition is true.
一个 if 嵌套在另一个 if 中。只有外层条件为 true 时,才会检查内层条件。
if-else-if (Multiway Selection)
if-else-if(多分支选择)
if (grade >= 90) { letter = "A"; } else if (grade >= 80) { letter = "B"; } else if (grade >= 70) { letter = "C"; } else { letter = "F"; }
true executes. All remaining branches are skipped. If none are true and there's a trailing else, that else runs.
true 的分支会执行,后面的分支全部跳过。若所有条件都不成立且末尾有 else,则执行该 else。
Compound Boolean Expressions
复合布尔表达式
Logical Operators
逻辑运算符(logical operator)
| Operator | Name | True When |
|---|---|---|
! | NOT | !a is true when a is false |
&& | AND | a && b is true only when both are true |
|| | OR | a || b is true when at least one is true |
| 运算符 | 名称 | 何时为真 |
|---|---|---|
! | 非(NOT) | 当 a 为假时,!a 为真 |
&& | 与(AND) | 当两者都为真时,a && b 才为真 |
|| | 或(OR) | 当至少一个为真时,a || b 为真 |
Precedence: ! → && → ||
优先级(precedence): ! → && → ||
int age = 20; boolean hasID = true; if (age >= 18 && hasID) { System.out.println("Entry allowed"); }
&&, if the first operand is false, the second is never checked.
With ||, if the first operand is true, the second is skipped.
This is important when the second expression could cause an error (e.g., null check).
short-circuit evaluation)
Java 一旦能确定整体结果就停止继续求值:
对 &&,若左操作数为 false,右操作数不再检查;
对 ||,若左操作数为 true,右操作数被跳过。
当右侧表达式可能抛错时(例如 null 判空),这点尤其重要。
String s = null; // Wrong order: s.length() runs first, throws NullPointerException if (s.length() > 0 && s != null) { ... } // Correct order: null check first, short-circuit skips s.length() if (s != null && s.length() > 0) { ... }
Why this matters on the exam: AP MCQs love to put the null check second, so the dangerous method call happens first. Short-circuit evaluation only saves you if the guard is on the left side of &&. Same idea with ||: put the "safe" condition that can short-circuit out the dangerous one on the left.
String s = null; // 顺序错误:先执行 s.length(),抛出 NullPointerException if (s.length() > 0 && s != null) { ... } // 顺序正确:先判空,短路会跳过 s.length() if (s != null && s.length() > 0) { ... }
为什么这在考试上重要: AP 选择题最爱把 null 判断放在第二位,让危险的方法调用先发生。只有把守卫条件放在 && 的左侧,短路求值才能救你。|| 同理:把可以短路掉危险条件的"安全"判断放在左边。
! binds tightest, then &&, then ||. So a || b && c is read as a || (b && c), not (a || b) && c. When in doubt, add parentheses. The AP rubric does not subtract points for "redundant" parentheses, but it does subtract for wrong groupings.
! 结合最紧,其次是 &&,最后是 ||。所以 a || b && c 应解读为 a || (b && c),而不是 (a || b) && c。拿不准时就加括号。AP 评分标准不会因"多余"的括号扣分,但会因错误分组扣分。
Comparing Boolean Expressions
比较布尔表达式
De Morgan's Law
德摩根定律(De Morgan's Laws)
| Original | Equivalent |
|---|---|
!(a && b) | !a || !b |
!(a || b) | !a && !b |
Flip the operator (&& ↔ ||) and negate each operand.
| 原式 | 等价式(equivalent) |
|---|---|
!(a && b) | !a || !b |
!(a || b) | !a && !b |
翻转运算符(&& ↔ ||),并对每个操作数取反。
Comparing Objects
比较对象
| Comparison | What It Checks |
|---|---|
obj1 == obj2 | Same reference (same object in memory)? |
obj1.equals(obj2) | Same content (as defined by the class)? |
obj == null | Does the reference point to no object? |
| 比较方式 | 检查什么 |
|---|---|
obj1 == obj2 | 同一个引用(内存中是同一个对象)? |
obj1.equals(obj2) | 相同内容(由类自行定义)? |
obj == null | 引用是否未指向任何对象? |
String a = new String("Hi"); String b = new String("Hi"); a == b // false, different objects// false,不同对象 a.equals(b) // true , same content// true,内容相同
!(x > 5 && y < 3)?!(x > 5 && y < 3) 等价?!(x>5) → x<=5, !(y<3) → y>=3, and && → ||.!(x>5) → x<=5,!(y<3) → y>=3,&& → ||。!(x>5 && y<3) = x<=5 || y>=3.!(x>5 && y<3) = x<=5 || y>=3。You want the opposite of "the student passed AND submitted on time".
// Original passed && onTime // Negated (apply De Morgan: flip && to ||, negate each side) !passed || !onTime
Read aloud: "the student failed OR was late". That matches your intuition for the opposite of "passed AND on time". If it doesn't match intuition, you probably flipped the operator without negating the operands (or vice versa).
你想得到"学生通过 AND 按时提交"的反面。
// 原式 passed && onTime // 取反(用德摩根:&& 翻成 ||,每一项取反) !passed || !onTime
读出来:「学生不及格 OR 没按时」。这正是"通过 AND 按时"的反面,与直觉一致。如果不一致,说明你只翻转了运算符却没把操作数取反(或者反过来)。
x > 5 is x <= 5, not x < 5. Always include the boundary value in the negation. Same logic: !(x == 5) becomes x != 5; !(x >= 5) becomes x < 5. Drop the "or equal" half exactly once per flip.
x > 5 的反是 x <= 5,不是 x < 5。取反时必须把边界值包进来。同理:!(x == 5) 变为 x != 5;!(x >= 5) 变为 x < 5。每次翻转时,"等于"那一半要恰好被丢掉一次。
while Loops
while 循环(while loop)
Iteration repeats code zero or more times while a condition is true.
循环(loop / iteration)会在条件为真时重复执行代码零次或多次。
int count = 1; while (count <= 5) { System.out.print(count + " "); count++; } // Output: 1 2 3 4 5// 输出:1 2 3 4 5
false, the body never executes.
false,循环体一次都不会执行。
false, the loop runs forever. Always ensure the loop body changes something that will eventually make the condition false.
infinite loop)
如果条件永远不会变成 false,循环就会一直跑下去。务必确保循环体中有某个变化最终能让条件为 false。
< vs <= (or starting at 0 vs 1) can cause a loop to run one time too many or too few. Trace carefully!
< 还是 <=(或从 0 起还是从 1 起)会让循环多跑一次或少跑一次。一定要仔细追踪!
int n = 20; int count = 0; while (n > 1) { n /= 2; count++; } // What is count?
Trace it:
| Iteration | n before body | n after n/=2 | count after |
|---|---|---|---|
| 1 | 20 | 10 | 1 |
| 2 | 10 | 5 | 2 |
| 3 | 5 | 2 | 3 |
| 4 | 2 | 1 | 4 |
| (check) | 1 | (loop exits, 1 > 1 is false) | 4 |
Final answer: count = 4. This is essentially counting how many times you can halve n until it drops to 1, which is roughly log2(n). A common AP pattern.
int n = 20; int count = 0; while (n > 1) { n /= 2; count++; } // count 等于多少?
逐步追踪:
| 第几次迭代 | 循环体前的 n | n/=2 后的 n | 之后的 count |
|---|---|---|---|
| 1 | 20 | 10 | 1 |
| 2 | 10 | 5 | 2 |
| 3 | 5 | 2 | 3 |
| 4 | 2 | 1 | 4 |
| (再次检查) | 1 | (退出循环,1 > 1 为假) | 4 |
最终答案:count = 4。这本质上是数 n 能被对半除多少次才降到 1,大约是 log2(n)。这是 AP 常见的套路。
for Loops
for 循环(for loop)
A for loop packs initialization, condition, and update into one header.
一个 for 循环把初始化、条件和更新打包在同一个头部里。
for (int i = 0; i < 5; i++) { System.out.print(i + " "); } // Output: 0 1 2 3 4// 输出:0 1 2 3 4
Three Parts of a for Header:
for (initialization; Boolean expression; update)
1. Init runs once before the loop starts.
2. Condition is checked before each iteration.
3. Update runs after each iteration's body, before the next check.
for 头部的三个部分:
for (初始化; 布尔表达式; 更新)
1. 初始化:循环开始前只执行一次。
2. 条件:每次迭代前都会检查。
3. 更新:每次循环体之后、下一次检查之前执行。
for loop can be rewritten as a while loop and vice versa:
for 循环都能改写成 while 循环,反之亦然:
// Equivalent while loop:// 等价的 while 循环: int i = 0; while (i < 5) { System.out.print(i + " "); i++; }
for (int i = 3; i < 8; i++)for (int i = 3; i < 8; i++)for (int i = 0; i < 5; i++) { // body runs with i = 0, 1, 2, 3, 4 } // after the loop, i = 5 (but only if i was declared OUTSIDE the for header)
The update step runs after every iteration, including the one that fails the condition. So i reaches the first value that makes the condition false. With i < 5, that's i = 5. With i <= 5, it's i = 6.
Catch: when i is declared inside the for header (for (int i = 0; ...)), it goes out of scope when the loop ends, and you can't read its final value. Declare i outside the header if you need it afterward.
loop variable)的最终值for (int i = 0; i < 5; i++) { // 循环体在 i = 0, 1, 2, 3, 4 下执行 } // 循环结束后,i = 5(仅当 i 在 for 头部之外声明时可见)
更新步骤在每次迭代后都会执行,包括让条件变假的那一次。所以 i 会到达让条件首次为假的那个值。i < 5 时是 i = 5;i <= 5 时是 i = 6。
注意: 当 i 在 for 头部内声明(for (int i = 0; ...))时,循环结束后 i 就出了作用域,你拿不到它的最终值。如果之后还要读它,就把 i 在头部外声明。
for (int i = a; i < b; i++) with a < b: iteration count is b - a. For i <= b: count is b - a + 1. For i += step: count is ceil((b - a) / step). Memorising the closed-form is faster than tracing the full loop on a timed MCQ.
for (int i = a; i < b; i++)(a < b):次数为 b - a。对 i <= b:次数为 b - a + 1。对 i += step:次数为 ceil((b - a) / step)。在限时选择题里,背公式比完整追踪更快。
Implementing Selection and Iteration Algorithms
实现选择与循环算法
The AP exam expects you to recognize and implement these standard algorithms:
AP 考试要求你能识别并实现下列标准算法(algorithm):
1. Divisibility Check
1. 整除性检查
if (num % 3 == 0) { System.out.println(num + " is divisible by 3"); }
2. Extract Digits
2. 提取数位
int n = 4827; while (n > 0) { int digit = n % 10; // last digit: 7, 2, 8, 4// 末位:7, 2, 8, 4 n /= 10; }
3. Count (Frequency)
3. 计数(频次)
int count = 0; for (int i = 1; i <= 100; i++) { if (i % 7 == 0) count++; }
4. Min / Max
4. 最小值 / 最大值
int max = Integer.MIN_VALUE; // As you process values:// 处理每个值时: if (val > max) max = val;
5. Sum / Average
5. 求和 / 平均
int sum = 0; for (int i = 1; i <= n; i++) { sum += i; } double avg = (double) sum / n;
Implementing String Algorithms
实现字符串算法
Standard string algorithms you should know:
你应当掌握的标准字符串算法(algorithm):
Traverse & Check Substrings
遍历并检查子串
String str = "hello world"; int vowels = 0; for (int i = 0; i < str.length(); i++) { String ch = str.substring(i, i + 1); if ("aeiou".indexOf(ch) >= 0) { vowels++; } }
Reverse a String
反转字符串
String original = "java"; String reversed = ""; for (int i = original.length() - 1; i >= 0; i--) { reversed += original.substring(i, i + 1); } // reversed = "avaj"// reversed = "avaj"
str.substring(i, i + 1) to get the character at index i as a String. This is the standard approach on the AP exam.
str.substring(i, i + 1) 把索引 i 处的字符作为 String 取出来。这是 AP 考试上的标准做法。
Nested Iteration
嵌套循环(nested loop)
A loop inside another loop. The inner loop completes all its iterations for each single iteration of the outer loop.
循环里再套循环。外层每跑一次,内层都要把它的所有迭代跑完。
for (int row = 1; row <= 3; row++) { for (int col = 1; col <= 4; col++) { System.out.print("* "); } System.out.println(); } // Output: // * * * * // * * * * // * * * *// 输出: // * * * * // * * * * // * * * *
for (int i = 1; i <= 4; i++) { for (int j = 1; j <= i; j++) { System.out.print("*"); } System.out.println(); }
Output:
* ** *** ****
When j's upper bound depends on i, you can't use the m × n shortcut. Total stars: 1 + 2 + 3 + 4 = 10, not 4 × 4 = 16. The shortcut only works when the inner loop bounds are constant across outer iterations.
for (int i = 1; i <= 4; i++) { for (int j = 1; j <= i; j++) { System.out.print("*"); } System.out.println(); }
输出:
* ** *** ****
当 j 的上界依赖于 i 时,不能套用 m × n 的捷径。星号总数:1 + 2 + 3 + 4 = 10,不是 4 × 4 = 16。这个捷径只在内层边界对每次外层迭代都不变时才适用。
println after the inner loop produces a row-and-column grid; println inside the inner loop puts each star on its own line; missing the println entirely produces one long row. Re-read where the newlines actually fall before picking an answer.
println 放在内层循环之后会形成行列网格;放在内层循环之内会让每个星号自占一行;完全没有 println 则全部挤成一长串。选答案前先把换行实际出现的位置看清楚。
Informal Run-Time Analysis
非形式化运行时分析
A statement execution count is the number of times a statement runs. You determine this by tracing the loop.
语句执行次数指一条语句被执行的次数。通过追踪循环来确定它。
| Structure | Execution Count Pattern |
|---|---|
| Single loop (1 to n) | Body runs n times |
| Nested loop (n × n) | Inner body runs n² times |
| Nested loop (n × m) | Inner body runs n × m times |
| 结构 | 执行次数公式 |
|---|---|
单层循环(loop,1 到 n) | 循环体执行 n 次 |
嵌套循环(nested loop,n × n) | 内层体执行 n² 次 |
| 嵌套循环(n × m) | 内层体执行 n × m 次 |
// How many times does the inner print execute?// 内层 print 共执行多少次? for (int i = 0; i < 5; i++) { // 5 times// 5 次 for (int j = 0; j < 3; j++) { // 3 times each// 每次 3 次 System.out.print("X"); // 5 × 3 = 15 times// 5 × 3 = 15 次 } }
"*" print?for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
System.out.print("*");"*" 会被打印多少次?for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
System.out.print("*");Unit 2 MCQ Patterns That Show Up Every Year
单元 2 每年都考的选择题套路
Unit 2 is the most-tested unit on the AP CSA MCQ section. Most questions fall into a handful of recurring shapes. Recognising the shape first lets you trace less and answer faster.
单元 2 是 AP CSA 选择题中考得最多的单元。大多数题都落在几种固定的套路里。先认出套路,就能少追踪、快出答案。
i < b starting at a, the count is b - a. For i <= b, it's b - a + 1. For i += step, count is ceil((b - a) / step). Skip the trace if you can spot the form. (See Topic 2.8.)
iteration)计数(公式法 vs 追踪法)
题目给出 for 循环头部,问循环体执行多少次。从 a 起的 i < b:次数为 b - a。i <= b:次数为 b - a + 1。i += step:次数为 ceil((b - a) / step)。能套公式就不要全程追踪。(见 2.8 节)
&& (or the "safe" condition that short-circuits). Order-of-operands MCQs are common. (See Topic 2.5.)
short-circuit evaluation)与 null 安全
带 null 判空的复合条件。正确的 AP 答案永远把 null 判断放在 && 的左侧(或者把能短路掉危险条件的"安全"判断放在左侧)。操作数顺序型选择题很常见。(见 2.5 节)
!(...)?" The mechanical answer: flip && ↔ || and negate each operand. Watch the relational flips: !(x > 5) is x <= 5, not x < 5. (See Topic 2.6.)
De Morgan's Laws)
"下列哪个与 !(...) 等价?" 机械做法:把 && ↔ || 翻过来,并对每个操作数取反。注意关系运算符的翻转:!(x > 5) 是 x <= 5,不是 x < 5。(见 2.6 节)
j ≤ i or j < n - i. Total iterations form a triangular sum (1 + 2 + ... + n = n(n+1)/2) or a reversed triangle. The m × n shortcut does not apply. (See Topic 2.11.)
nested loop)
内层循环跑 j ≤ i 或 j < n - i。总迭代次数构成三角和(1 + 2 + ... + n = n(n+1)/2)或反向三角。这种情况下 m × n 的捷径不适用。(见 2.11 节)
< vs <=. Trace the boundary cases: what happens at the first and last value? The "correct" formula usually pairs with the inclusive or exclusive endpoint of the problem statement. (See Topic 2.7.)
< 与 <= 上有差别。追踪边界情况:第一个值和最后一个值各会怎样?"正确"公式通常与题面里端点是闭还是开相匹配。(见 2.7 节)
println with a forced line break and trace iteration by iteration. (See Topic 2.11.)
println 都标记为强制换行,然后一轮一轮地追踪。(见 2.11 节)
Flashcards, Click to Flip
闪卡,点击翻面
!(a && b) = ?德摩根:!(a && b) = ?!a || !b!(a || b) = ?德摩根:!(a || b) = ?!a && !bfalse && ... → skips 2ndtrue || ... → skips 2ndResult already determined.
false && ... → 跳过右侧true || ... → 跳过右侧结果已经确定。
false.布尔条件永远不会变成 false。< vs <=).循环多跑或少跑一次(如 < 与 <= 用错)。== vs .equals()?== → compares references.equals() → compares content== → 比较引用.equals() → 比较内容↻ Check → Body → Update …初始化 → 检查 → 循环体 → 更新
↻ 检查 → 循环体 → 更新 …
n % 10Unit 2, Practice Quiz
单元 2 练习小测
int x = 15;
if (x > 20) print("A");
else if (x > 10) print("B");
else if (x > 5) print("C");
else print("D");int x = 15;
if (x > 20) print("A");
else if (x > 10) print("B");
else if (x > 5) print("C");
else print("D");count hold after this loop?int count = 0;
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) count++;
}count 的值是多少?int count = 0;
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) count++;
}!(a || !b)?!(a || !b) 等价?!(a || !b) = !a && !!b = !a && b.!(a || !b) = !a && !!b = !a && b。!a && !!b = !a && b.!a && !!b = !a && b。int n = 1234; int sum = 0;
while (n > 0) { sum += n % 10; n /= 10; }
System.out.println(sum);int n = 1234; int sum = 0;
while (n > 0) { sum += n % 10; n /= 10; }
System.out.println(sum);"!" print?for (int i = 1; i <= 3; i++)
for (int j = 1; j <= i; j++)
System.out.print("!");"!" 会被打印多少次?for (int i = 1; i <= 3; i++)
for (int j = 1; j <= i; j++)
System.out.print("!");AP-Style Practice Problems
AP 风格练习题
15 exam-level multiple-choice questions (3 medium · 12 hard), code-trace heavy with realistic distractors and fully worked solutions. Built for top-score prep — go here after you've worked through the notes and the in-page quiz above.
15 道考试级别的选择题(3 道中等 · 12 道困难),以代码追踪为主,配真实迷惑选项与完整解答。为冲高分而设——把上面的笔记和小测做完后再来挑战。
鼎睿学苑 · Dingrui Scholars
AP Computer Science A, Unit 2: Selection & Iteration · 2026 Edition
AP 计算机科学 A · 单元 2:选择与循环 · 2026 版