How to Solve AP CSA Free Response Questions: A Step-by-Step Strategy
Share
How to Solve AP CSA Free Response Questions: A Step-by-Step Strategy
By Tanner Crow — AP Computer Science Teacher & Tutor • 1,845+ Hours Tutored • 451 Five-Star Reviews
Table of Contents
What the AP CSA FRQ Section Looks Like
The AP CSA exam dedicates the entire second section to four free-response questions. You get 90 minutes total, which works out to roughly 22 minutes per question. Each FRQ is scored on a rubric worth 9 points. The four question types you will encounter map to the 2025–2026 curriculum units:
| FRQ # | Question Type | Primary Unit Alignment |
|---|---|---|
| FRQ 1 | Methods and Control Structures | Unit 2: Selection & Iteration |
| FRQ 2 | Class Writing | Unit 3: Objects & Classes |
| FRQ 3 | Array / ArrayList | Unit 4: Data Collections |
| FRQ 4 | 2D Array | Unit 4: Data Collections |
Each question may have two or three parts labeled (a), (b), and sometimes (c). Parts are scored independently. A wrong answer in part (a) does not prevent you from earning full credit in part (b) if you use your part (a) method correctly in part (b), even if that method was incorrect.
Before You Read the Options: Predict First
This principle is not just for multiple-choice questions. It applies to free-response problems too. Before you write a single line of Java, you should already have a mental model of what a correct solution looks like. This is called answer prediction, and it is one of the most powerful habits you can build.
The same logic applies when reviewing answer choices on the multiple-choice section. Students who formulate their own answer before reading options are far less likely to be swayed by a convincing but wrong distractor. On the FRQ side, students who sketch a pseudocode plan before writing Java write cleaner, more complete solutions.
The 5-Step FRQ Framework
Read the full question from top to bottom before touching your answer sheet. As you read, physically underline or circle these four things:
- The return type of every method you must write
- Parameter names and their types
- Methods already provided that you are allowed to call
- Edge cases or special conditions mentioned in the problem description
Once you know the question type, you know the pattern. Experienced test-takers recognize these instantly:
- Methods & Control Structures: You are completing one or two methods. Look for a for/while loop opportunity and a conditional inside it.
- Class Writing: You are writing constructors, instance variables, and methods. Always declare private instance variables. Always write a full constructor. Return the correct type from each method.
-
Array / ArrayList: You are traversing and either accumulating, filtering, or restructuring. Identify whether you need an index-based for-loop, a for-each loop, or ArrayList methods like
add(),remove(), andget(). - 2D Array: You need a nested loop. Outer loop = rows, inner loop = columns, unless specified otherwise.
Spend 2–3 minutes writing pseudocode or annotated English in the margin. Your plan should answer:
- What data structure am I working with?
- What loop type do I need and what are the bounds?
- What is the condition for the branch inside the loop?
- What do I accumulate, return, or modify?
- Which provided methods should I call, and where?
FRQ rubrics award points for specific, identifiable pieces of logic. Write code with those checkpoints in mind. Leave space between lines in case you need to insert something. Common rubric checkpoints include:
- Correct method header (matches the signature given)
- Loop with correct bounds
- Correct access of array elements or ArrayList elements inside the loop
- Correct conditional logic
- Correct return statement with the right type
Each checkpoint is worth a point. You do not have to write perfect, elegant code. You need to hit the rubric checkpoints. Incomplete code that hits 6 checkpoints earns 6 points. Elegant code that misses a return type earns less.
With 3 minutes remaining for the question, audit your code against the problem:
- Trace through the provided examples and verify your output matches
- Check for off-by-one errors at loop boundaries
- Confirm every method you were told to write actually has a return statement
- Confirm you used the provided helper methods where the question expected them
- Remove any code that has unintended side effects (printing to output when not asked, modifying a parameter you were not supposed to modify)
Full Worked Example: Applying the Framework
Let us apply all five steps to a representative FRQ prompt. This is an original practice problem modeled on the FRQ 3 (Array / ArrayList) style.
ScoreTracker class manages a list of integer scores from a quiz. You will write two methods for this class.Method headers provided:
public int countAbove(int threshold)public void removeBelow(int cutoff)Instance variable:
private ArrayList<Integer> scores; (already initialized)(a) Write the
countAbove method. It should return the number of elements in scores that are strictly greater than threshold.(b) Write the
removeBelow method. It should remove all elements from scores that are strictly less than cutoff.
Step 1 — Read Actively
Underline: return type int (part a), void (part b), parameter threshold, parameter cutoff, "strictly greater than," "strictly less than," instance variable scores is an ArrayList.
Step 2 — Identify the Pattern
FRQ 3 / ArrayList. Part (a) is a counting pattern — traverse and accumulate. Part (b) is a removal pattern — traverse backwards or use an iterator to safely remove during traversal.
remove(), you will skip elements immediately after a removal because the indices shift. You must traverse backwards (from size − 1 down to 0) or use an iterator. The AP readers know this trap and the rubric rewards handling it correctly.
Step 3 — Predict the Plan
Part (a): Initialize a counter to 0. Loop through scores. If current score > threshold, increment counter. Return counter.
Part (b): Loop from the last index down to 0. If current score < cutoff, call scores.remove(i).
Step 4 — Write the Java
Return type is
int — you need a counter variable.You are not removing anything, so a for-each loop is safe.
The condition is strictly greater-than (not greater-than-or-equal).
The method must have an explicit
return count; at the end.If you had all four of those before reading the solution below, you were ready to write it without looking.
public int countAbove(int threshold) { int count = 0; // accumulator for (int score : scores) { // for-each is safe here (no removal) if (score > threshold) { count++; } } return count; }
If you remove an element at index
i while traversing forward, the element at index i+1 silently shifts into position i and is never examined. Consecutive targets will be partially skipped.Two valid fixes — pick one and commit:
1. Traverse backwards: start at
scores.size() - 1, decrement to 0. Removals only affect indices above the current position, which you have already passed.2. Traverse forward but add
i-- immediately after each remove(i) call so the index stays at the same position next iteration.If you identified the trap and chose an approach before looking, you already understand the hardest part of this problem.
public void removeBelow(int cutoff) { for (int i = scores.size() - 1; i >= 0; i--) { // backwards traversal if (scores.get(i) < cutoff) { scores.remove(i); // index-based remove } } }
Step 5 — Verify
Trace with scores = [85, 42, 91, 60, 38], threshold = 70, cutoff = 50:
Once you have your prediction, expand the trace below to check.
countAbove(70): 85 > 70 (count=1), 42 ≤ 70, 91 > 70 (count=2), 60 ≤ 70, 38 ≤ 70. Returns 2. Correct.
removeBelow(50): i=4: 38 < 50, remove. List=[85,42,91,60]. i=3: 60 ≥ 50, keep. i=2: 91 ≥ 50, keep. i=1: 42 < 50, remove. List=[85,91,60]. i=0: 85 ≥ 50, keep. Final list=[85,91,60]. Correct.
How Rubric Points Are Awarded
The College Board rubric for FRQ 3 typically awards one point each for: correct loop structure, correct ArrayList access inside the loop, correct conditional, correct accumulator or modification, and correct return value. For a removal question, an additional point is awarded specifically for a traversal method that correctly handles index shifting. That is the backwards-traversal point, and it is one of the most commonly missed.
length vs .length() or .size() where context is obvious. You are not penalized for these. Focus on logic, not perfect syntax.
The 4 Most Costly FRQ Mistakes
After reviewing hundreds of student FRQ submissions — both in class and through AP CSA tutoring sessions — the same four errors appear on nearly every score report in the 5–7 range. Fixing just these four moves most students into the 8–9 range.
1. Not calling the provided methods. The question gives you helper methods for a reason. If you reimplement the logic manually instead of calling the provided method, you may still get the logic point but lose the method-call point. Read the class interface carefully and use what is given.
2. Writing code that only solves the example. The rubric tests general logic. Hard-coding values that work on the example input but fail on a general case gets zero credit for that rubric point.
3. Forgetting the return statement. This is the most common 8-out-of-9 mistake. A void method that accidentally has a return statement is a penalty. A non-void method missing its return statement misses the return-value rubric point. Always check.
4. Forwards traversal with ArrayList removal. Covered above. This costs the traversal correctness point, which is often worth 1–2 points on ArrayList removal questions.
Practice: Test Your FRQ Strategy Knowledge
Before reading the answer choices, predict what you think is wrong or correct. Then select your answer and check your reasoning.
public void removeAll(ArrayList<Integer> list, int target) { for (int i = 0; i < list.size(); i++) { // Line 1 if (list.get(i) == target) { // Line 2 list.remove(i); // Line 3 } // Line 4 } }
-
(A) Line 1, because
i < list.size()does not account for an empty list -
(B) Lines 1 and 3 together, because removing an element at index
ishifts subsequent elements left, so the element immediately after each removed value is skipped -
(C) Line 2, because
==cannot compareIntegerobjects for value equality when values exceed 127 -
(D) Line 3, because
ArrayList.remove(int index)should be replaced withArrayList.remove(Integer.valueOf(target))on every iteration
The error is the interaction between Lines 1 and 3. When
remove(i) is called, all elements after index i shift left by one position. On the next iteration, i increments, but the element that shifted into index i has never been examined. If two consecutive target values appear in the list, only the first is removed. The fix is to decrement i after removal (i--) or traverse backwards from list.size() - 1 down to 0. Option (C) is a plausible distractor because == on boxed Integers is unreliable above 127, but on this exam target is passed as a primitive int and auto-unboxing makes == reliable here. Option (D) would be an alternative approach but is not the primary error causing skipped elements.
int[] field named data:
public int findMax() { int max = 0; for (int i = 0; i < data.length; i++) { if (data[i] > max) { max = data[i]; } } return max; }
I. The method returns 0 instead of the correct maximum when all values in
data are negative.II. The method throws an
ArrayIndexOutOfBoundsException when data has exactly one element.III. Initializing
max to data[0] instead of 0 would eliminate the defect without introducing new errors, provided data is guaranteed non-empty.
[-5, -3, -9] mentally. What does max = 0 return vs. the true maximum?For Statement II: trace the loop when
data.length == 1. Does i ever reach an out-of-bounds index?For Statement III: if
data[0] is the starting value, does any all-negative array still fool the method?Decide true/false for each, then select below.
- (A) I only
- (B) II only
- (C) I and III only
- (D) I, II, and III
Statement I is TRUE. Initializing
max = 0 means any array containing only negative values (e.g., [-5, -3, -9]) will return 0, which is incorrect because 0 is not in the array. This is a genuine defect.Statement II is FALSE. When
data.length is 1, the loop runs from i = 0 to i < 1, so i = 0 executes exactly once and no out-of-bounds access occurs. There is no exception.Statement III is TRUE. Initializing
max = data[0] corrects the all-negative defect because the starting sentinel is guaranteed to be an actual value in the array. As long as the precondition states data is non-empty, this fix is valid.
value.
public class Counter { private int value; public Counter(int value) { value = value; // intended to initialize instance variable } public int getValue() { return value; } }
new Counter(10).getValue() return?
value: the parameter and the instance variable. When they share a name, which one does Java use on each side of the assignment? Does the instance variable ever get updated? What is its default value if it is never set? Form your answer before selecting below.
-
(A) 0, because the assignment
value = valueassigns the parameter to itself and the instance variable is never set, defaulting to 0 -
(B) 10, because Java resolves the left-hand
valueto the instance variable and the right-handvalueto the parameter - (C) A compile-time error, because a local variable and an instance variable cannot share the same name
-
(D) An unpredictable value, because the behavior of
value = valueis undefined when names conflict
This is one of the most frequently tested "spot the bug" scenarios on FRQ 2. When a constructor parameter has the same name as an instance variable, the parameter shadows the instance variable inside that method. The line
value = value assigns the parameter to itself, which is a no-op. The instance variable this.value is never touched, so it retains its default value of 0. The correct fix is this.value = value;. Java does not produce a compile-time error for this code, which is why it is such a dangerous mistake to make on the exam.
isValid method written in part (a), but the student's part (a) solution has a logic error. The student knows part (a) is wrong. Which of the following approaches is most likely to maximize their total score across both parts?I. Rewrite part (a) from scratch to fix the logic error, then write part (b) calling the corrected version.
II. Leave part (a) as-is. In part (b), call
isValid exactly as the rubric expects, even though the student knows it is incorrect.III. Skip part (a) entirely and write only part (b), defining an inline version of the helper logic directly inside part (b).
- (A) I only, because a correct part (a) is required to earn any credit in part (b)
-
(B) I or II depending on the time remaining; II is valid because part (b) is scored independently, and calling
isValidcorrectly earns the method-call point regardless of whether part (a) is correct - (C) III only, because the reader cannot penalize a solution that produces correct output
- (D) II only, because attempting to fix part (a) risks introducing new errors that could reduce the part (a) score further
This is a critical exam-day strategy point. AP CSA FRQ rubrics explicitly state that parts are scored independently. Even if part (a) earns 0 points due to a logic error, part (b) can still earn full credit if it calls
isValid appropriately and implements the correct surrounding logic. If you have time remaining, attempt to fix part (a) because that maximizes your potential points across both parts. If you are running short on time, move to part (b) and call the method as the rubric expects — you will still earn the method-call point. Option (C) is tempting but risky: reimplementing logic inline when the rubric expects a method call often loses the method-call point on the rubric, even if the output would be correct.
Keep Practicing With Real FRQs
The fastest way to internalize this framework is to apply it to official College Board questions from previous exams. Every study guide below is aligned to the 2025–2026 4-unit curriculum.
Want to walk through FRQs with someone who has done this 1,800+ times?
If you are hitting a wall on a specific FRQ type or just want guided practice before the exam, one-on-one AP CSA tutoring sessions are available. Sessions focus on exactly the kind of structured problem-solving covered in this guide — no busywork, no re-teaching things you already know. Most students see meaningful improvement in FRQ scores within two or three sessions.
Learn About Tutoring