AP CSA FRQ Strategy Guide 2026 | Algorithms, Patterns, & Scoring (Free)
AP CSA FRQ Strategy Guide 2026: Algorithms, Patterns & Scoring
Every algorithm pattern, every FRQ type decoded, the official scoring rules, and the 7-step rescue protocol. Built from the College Board CED for the May 15, 2026 exam — written by Tanner Crow.
The exam structure shrunk in your favor. Q3 and Q4 are now 1 method each (used to be 2). Q2 is 1 constructor + 1 method (used to be a full class with multiple methods). Same total points, more time per question. Use the saved time to plan and trace before coding.
Other 2025-2026 facts: 4 FRQs · 45% of your total score · 90 minutes · fully digital via Bluebook · Java Quick Reference provided. The exam removed inheritance, extends, super, and interfaces. FRQ 3 is ArrayList-only.
Part 1Time Strategy (90 min ÷ 4 FRQs)
Don't try to spend 22.5 minutes on each question. The questions aren't equal weight, and your speed depends on the type. Here's how to budget:
| FRQ | Type | Target time | Points |
|---|---|---|---|
| Q1 | Methods & Control Structures (constructor + method OR 2 methods) | 20 min | 7 pts |
| Q2 | Class Design (1 constructor + 1 method) | 25 min | 7 pts |
| Q3 | ArrayList: 1 method (traversal/filter/accumulate) | 20 min | 5 pts |
| Q4 | 2D Array: 1 method (nested traversal) | 20 min | 6 pts |
| Plan + review buffer | 5 min |
If you finish a question early, move on. If you get stuck, write the method signature, javadoc-style comments, and partial logic to earn partial credit before skipping. Never leave a part blank — the signature alone often unlocks 1-2 points.
Part 2The 4 FRQ Slots (Verified vs. Official CED)
Q1 — Methods and Control Structures (7 pts)
- Write two methods OR one constructor and one method of a given class.
- Part A (4 pts): requires iterative or conditional statements, plus calls to methods in the specified class.
- Part B (3 pts): requires String methods (substring, indexOf, equals, length, compareTo).
- If a second class is referenced, a variable of that type is passed in — call its methods on that variable, do NOT instantiate a new one.
- Common Part A patterns: accumulator, count, find-first, build-new-string, while-not-null loop.
walker, you must write walker.getDistance() — NOT just getDistance(). Always dot-notation off the given variable name.Q2 — Class Design (7 pts)
- Write the complete class: class header + private instance variables + 1 constructor + 1 method. That's it.
- Read the provided method table FIRST: it shows constructor signature, return types, and a plain-English explanation for each method — use it as your blueprint.
- In the table: constructor row = what to initialize; return type column = what to declare; explanation column = your algorithm.
- Every field they describe, you declare as a private instance variable.
- Constructor must initialize all fields. The method must read or modify state.
- A second class may be referenced — if so, treat its objects as parameters, don't try to write that class.
String, your method signature must say String. Don't over-engineer: write only the constructor and method they ask for, even if you think the class "needs" more methods.Q3 — Data Analysis with ArrayList (5 pts)
- Just 1 method. Usually traverse + filter + accumulate or count.
- The ArrayList holds objects of a provided class — you'll call getter methods on each element (e.g.
it.getCost(),it.isAvailable()). - Adjacent comparison: compare
list.get(i)withlist.get(i+1)— loop only tosize()-1to avoid IndexOutOfBoundsException. - Nested pair comparison: outer
ifrom 0 tosize()-1, innerjfromi+1tosize(). - Filter/remove: iterate backward OR decrement
iafter remove to avoid skipping elements. - Use enhanced for-each when you don't need indices — cleaner code, fewer off-by-one bugs.
-
size()not length;get(i)not[i];remove(i)shifts right elements left.
size() instead of size()-1 causes get(i+1) to throw IndexOutOfBoundsException on the last iteration. In nested pair loops, starting inner loop at 0 instead of i+1 double-counts every pair.Q4 — 2D Array (6 pts)
- Just 1 method. Usually nested-loop traversal: outer = rows, inner = cols (or vice versa for column-major).
- Like Q3, the 2D array typically holds objects — call getter methods on each cell (e.g.
sched[r][c].getStatus()). -
Row-major: outer
rfrom 0 toarr.length, innercfrom 0 toarr[0].length. -
Column-major: outer
cfrom 0 toarr[0].length, innerrfrom 0 toarr.length. Use this when comparing within columns. - Track-the-max/min pattern: maintain a
bestIndexandbestValueoutside the loop, update inside. - Watch off-by-one:
arr.length= number of rows;arr[0].length= number of cols.
arr.length (rows) with arr[0].length (cols). When the question says "column with the fewest occurrences," you need column-major traversal: outer loop is the column index, inner loop is the row index. Reset your per-column counter at the START of each outer iteration.Q1 = String + a class method. Q2 = build the class. Q3 = ArrayList of objects, call getters. Q4 = 2D array of objects, call getters. Three out of four FRQs require calling getter methods on objects you don't control. Practice that skill specifically.
Part 3Algorithm Pattern Library
These are the 13 patterns that show up across virtually every AP CSA FRQ. Memorize them, and Q1-Q4 become assembly rather than invention.
int total = 0;
for (int i = 0; i < arr.length; i++) {
total += arr[i];
}
return total;
int count = 0;
for (String s : list) {
if (s.length() > 3) {
count++;
}
}
return count;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target) {
return i;
}
}
return -1; // not found sentinel
ArrayListresult = new ArrayList (); for (String s : original) { if (meetsCondition(s)) { result.add(s); } } return result;
for (int i = list.size() - 1; i >= 0; i--) {
if (shouldRemove(list.get(i))) {
list.remove(i);
}
}
double sum = 0.0;
int count = 0;
for (Item it : inventory) {
if (it.isAvailable() && it.getCost() >= lower
&& it.getCost() <= upper) {
sum += it.getCost();
count++;
}
}
return sum / count;
// Loop to size()-1 to avoid IndexOutOfBoundsException
for (int i = 0; i < list.size() - 1; i++) {
if (list.get(i).equals(list.get(i + 1))) {
// adjacent duplicates found
}
}
// Start inner at i+1 to avoid duplicate comparisons
for (int i = 0; i < list.size() - 1; i++) {
for (int j = i + 1; j < list.size(); j++) {
if (list.get(i).equals(list.get(j))) {
// matching pair at i and j
}
}
}
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[0].length; c++) {
// process grid[r][c]
}
}
// Use this when comparing values WITHIN a column
int bestCol = 0;
int bestCount = grid.length; // max possible
for (int c = 0; c < grid[0].length; c++) {
int count = 0;
for (int r = 0; r < grid.length; r++) {
if (grid[r][c].getStatus().equals(target)) {
count++;
}
}
if (count < bestCount) {
bestCount = count;
bestCol = c;
}
}
return bestCol;
// Build first letter of each word
String temp = message;
String result = temp.substring(0, 1);
while (temp.indexOf(" ") >= 0) {
int i = temp.indexOf(" ");
temp = temp.substring(i + 1);
result += temp.substring(0, 1);
}
return result;
// Use when a helper returns null to signal end
String w = getNextWord(start);
while (w != null) {
message += " " + w;
count++;
w = getNextWord(w);
}
// Random int in [lo, hi] inclusive int n = (int)(Math.random() * (hi - lo + 1)) + lo; // Random index into array: int idx = (int)(Math.random() * arr.length);
Part 4String Methods Deep Dive (Q1 Part B is ALWAYS this)
| Method | Returns | Example |
|---|---|---|
| str.length() | int |
"hello".length() → 5 |
| str.substring(i, j) | String |
"hello".substring(1,3) → "el" |
| str.substring(i) | String |
"hello".substring(2) → "llo" |
| str.indexOf("x") |
int (-1 if missing) |
"hello".indexOf("l") → 2 |
| str.equals("x") | boolean |
Never use == for Strings |
| str.compareTo("x") |
int (<0 / 0 / >0) |
Alphabetical order comparison |
// substring is on the Quick Reference; charAt is not. // Use substring -- comparisons stay String-based with .equals(). str.substring(i, i + 1) // returns a one-char String
if (str.substring(0, 1).equals("A")) {
// starts with A
}
if (str.substring(str.length() - 1).equals("z")) {
// ends with z
}
if (str.indexOf("ing") != -1) {
// "ing" is present somewhere
}
// compareTo returns < 0 if str1 comes BEFORE str2
if (str1.compareTo(str2) < 0) {
// str1 is alphabetically first
}
int sp = str.indexOf(" ");
String first = str.substring(0, sp);
String rest = str.substring(sp + 1);
int count = 0;
for (int i = 0; i < str.length(); i++) {
if (str.substring(i, i + 1).equals("a")) {
count++;
}
}
charAt() is NOT listed on the official 2025-2026 Java Quick Reference. It still works in Java, but the safer strategic choice is str.substring(i, i+1) — it's listed, returns a String (so you compare with .equals()), and avoids the char-arithmetic traps that have cost students points historically. If you've trained on charAt, you can keep using it. If you're unsure, use substring.
Part 5Math Methods Deep Dive
| Method | Returns | Example |
|---|---|---|
| Math.abs(x) | same type | Math.abs(-5) → 5 |
| Math.pow(b, e) | double |
Math.pow(2, 3) → 8.0 |
| Math.sqrt(x) | double |
Math.sqrt(9) → 3.0 |
| Math.random() |
double [0, 1) |
See random-int formula |
| Math.max(a, b) | same type | Math.max(3, 7) → 7 |
| Math.min(a, b) | same type | Math.min(3, 7) → 3 |
// Random int in [lo, hi] inclusive int n = (int)(Math.random() * (hi - lo + 1)) + lo;
int idx = (int)(Math.random() * arr.length);
int q = 7 / 2; // q = 3, NOT 3.5 int rem = 7 % 2; // rem = 1
double avg = (double) sum / count; // cast ONE operand
int clamped = Math.min(Math.max(val, lo), hi);
int diff = Math.abs(a - b);
Part 6Object Method Patterns (3 of 4 FRQs Need This)
FRQs give you a class with methods. You must call those methods on objects, not access fields directly. These patterns cover every exam scenario.
for (Student s : roster) {
int g = s.getGrade(); // call method, not s.grade
if (g >= 90) {
count++;
}
}
for (int i = 0; i < items.length; i++) {
String name = items[i].getName();
}
// If getScore() returns a ScoreRecord with getTotal(): int total = player.getScore().getTotal();
// FRQ says "use the provided method someHelper(x)"
public int myMethod(int x) {
return someHelper(x) + 1; // call it directly
}
public class Box {
private int size;
public Box(int size) {
this.size = size; // this.size = field, size = param
}
}
ArrayListdeck = new ArrayList (); for (int v = 1; v <= 13; v++) { deck.add(new Card(v, "Hearts")); }
Part 7Official Penalties (and What's Forgiven)
Penalty points are only deducted in a part that already earned credit. No part can go negative. Max 3 penalty points per question. Each penalty applies only ONCE per question even if repeated.
1-point penalties (avoid these)
- Array/collection access confusion: using
[]instead of.get()when assessed - Extraneous code that causes a side effect (e.g. printing to output, broken precondition check)
- Local variable used but none declared anywhere
- Destruction of persistent data (e.g. modifying value referenced by a parameter)
- Returning a value from a void method or constructor
Errors graders forgive (no penalty)
- Extraneous code with NO side effect (valid precondition check, no-op)
- Spelling/case discrepancy where correction is unambiguous (e.g.
ArayList) - Local variable not declared, IF other variables are declared in some part
-
private/publicqualifier on a local variable - Missing
publicqualifier on class or constructor header - Keyword used as an identifier
- Math symbols used for operators (× · ÷ ≤ ≥ <> ≠)
-
[]vs()vs<>confusion -
=instead of==and vice versa -
length/sizeconfusion for array, String, List, ArrayList; with or without() - Extraneous
[]when referencing entire array -
[i,j]instead of[i][j] - Extraneous size in array declaration:
int[size] nums = new int[size] - Missing
;where structure clearly conveys intent - Missing
{ }where indentation clearly conveys intent - Missing
()on parameter-less method calls - Missing
()around if/while/for conditions
Part 8Pre-Code Planning Ritual (4 minutes)
Do this BEFORE writing any code. Students who skip planning write twice as much wrong code.
Step 1 (30 sec) — Read the WHOLE question
Read every part (a), (b), (c) before writing anything. Underline: return type, parameter names, what the method DOES. Circle: any provided methods you are required or allowed to call.
Step 2 (30 sec) — Classify the algorithm
Is this: accumulate / count / find / build-list / remove / 2D traverse? Pick the pattern from Part 3. Write the loop skeleton FIRST (header + braces), then fill in body.
Step 3 (1 min) — Write method signature
public [returnType] [methodName]([params]) {. If you are writing a class (Q2), list all fields and constructor first. Write the return statement placeholder: return ____;
Step 4 (1 min) — Trace a small example by hand
Pick 2-3 values and trace what your loop should do step by step. If the output doesn't match what the problem says, fix BEFORE coding.
Step 5 (1 min) — Write the code
Fill in the loop body based on your trace. Use the Quick Reference for ArrayList/String/Math method names.
Part 9"I'm Stuck" 7-Step Rescue Protocol
Working through these in order earns you partial credit even if you can't fully solve the problem. Do not skip ahead. Each step is its own potential point.
1. Write the method signature and a placeholder return statement
public int findTotal(int[] nums) {
// ...
return 0; // placeholder
}
2. Write what the method is SUPPOSED to do in a comment
// This method sums all values in nums that are > 0
3. Identify which pattern this is (Part 3 of this guide)
// Pattern: Accumulator -- need a running total variable
4. Write the loop skeleton, even if empty
for (int i = 0; i < nums.length; i++) {
// TODO
}
5. Write ONE line inside the loop you are confident in
total += nums[i]; // add each element
6. Add the condition if needed
if (nums[i] > 0) {
total += nums[i];
}
7. Replace placeholder return with real return
return total;
Part 10Partial Credit Strategies
Each FRQ is worth 5-7 points distributed across multiple criteria. You can earn 3-5 points with a partially correct answer. Never leave a question blank.
Write the method signature correctly
Worth 0 direct points but required before any other points. No signature = 0 on that part.
Declare and initialize the right variable type
Example: ArrayList earns the "creates list" point.
Write a correct loop structure even with wrong body
A correct for loop with correct bounds often earns 1 point even if the body is wrong.
Call the right method name (even with wrong args)
list.remove(...) earns the "uses remove" point even if the index is off.
Return the correct type even if the value is wrong
return result; earns the "returns list" point even if result isn't fully built.
Write javadoc-style comments explaining intent
Graders may give benefit of the doubt if your intent is clear and the code partially implements it.
Stuck with 3 minutes left? Write signature + return type + ONE correct statement per part. Earn 2-3 points across multiple parts rather than 0. This single tactic has saved more 4s and 5s than any other.
Part 11Top 10 Killer Mistakes
1. Using == to compare Strings
if (s == "hello") { } // WRONG
if (s.equals("hello")) { } // CORRECT
2. Using [] to access ArrayList elements
list[i] // WRONG list.get(i) // CORRECT
3. Using .length for ArrayList
list.length // WRONG list.size() // CORRECT
4. Removing from ArrayList while iterating forward
// WRONG: forward loop skips element after each remove
// CORRECT: iterate backward
for (int i = list.size() - 1; i >= 0; i--) {
if (shouldRemove(list.get(i))) {
list.remove(i);
}
}
5. Integer division truncates silently
double avg = sum / count; // WRONG (both ints) double avg = (double) sum / count; // CORRECT
6. Off-by-one in loops
// WRONG -- ArrayIndexOutOfBoundsException:
for (int i = 1; i <= arr.length; i++) { }
// CORRECT:
for (int i = 0; i < arr.length; i++) { }
7. Modifying a parameter array/list (destroys persistent data)
// -1 penalty: changing values in the passed-in array directly // Read from it; do not reassign its elements
8. Returning a value from a void method or constructor
// void method: return; is OK // return someValue; inside void method = -1 penalty
9. Treating charAt() like it's on the Quick Reference
str.charAt(i) // works, but NOT on the Quick Ref str.substring(i, i + 1) // listed -- safer choice // substring returns a String, so use .equals() to compare
10. Forgetting to initialize accumulator variables
// WRONG: int total; total += x; // CORRECT: int total = 0; total += x;
11+ years teaching AP Computer Science A. 54.5% of my students score 5s compared to 25.5% nationally — more than double the national rate. 1,800+ verified Wyzant tutoring hours, 5.0 rating from 451+ reviews. I built this guide because every student who actually works the patterns can earn that 5.
Want this strategy plus a daily plan?
If you've made it to the end of this guide, you're serious about the exam. The Cram Kit is the natural next step — daily MCQs, written response practice, and a structured plan through May 15.
Want a question every morning until exam day?
The free AP CSA Question of the Day delivers one practice MCQ to your inbox each morning, with full explanation. Solid drilling, zero spam.
Get the daily question →Get in Touch
Whether you're a student, parent, or teacher — I'd love to hear from you.
Just want free AP CS resources?
Enter your email below and check the subscribe box — no message needed. Students get daily practice questions and study tips. Teachers get curriculum resources and teaching strategies.
Message Sent!
Thanks for reaching out. I'll get back to you within 24 hours.
Prefer email? Reach me directly at [email protected]