2D Arrays – FRQ Practice (AP Computer Science A)
Practice the 2D array patterns used in AP Computer Science A, including row and column traversal, grid analysis, boundary checks, and scenario-based algorithms. Work through 15 original AP CSA–style problems with Java solutions and common-mistake explanations.
AP CSA Assumption: Unless a problem states otherwise, assume a 2D array is rectangular, meaning every row has the same number of columns. For the AP CSA exam, 2D arrays are also assumed to contain at least one row and one column.
Why Practice 2D Array FRQs?
AP CSA Free Response Questions involving 2D Arrays commonly test:
- Row-major (row-by-row) vs Column-major (column-by-column) traversal patterns.
- Accumulating sums, finding maximums, or counting specific object properties in a grid.
- Checking boundary conditions to prevent
ArrayIndexOutOfBoundsException. - Processing adjacent neighbors (up, down, left, right).
- Modifying specific cells in a 2D array based on conditional logic.
AP CSA 2D Array Concepts You Should Know

AP CSA 2D Arrays Quick Reference: indices, traversal patterns, neighbor checks, and common Java algorithms.
How to Use This FRQ Practice Page
- Try to write out each problem independently on paper first.
- Compare your bounds checking with the provided solution.
- Study the Common Mistakes section to avoid out-of-bounds exceptions.
- Reattempt until you can construct nested loops automatically.
FRQ 1 — Count Zeros in a 2D Array
Write a method countZeros(int[][] grid) that returns how many elements in the 2D array are equal to 0.
{{1, 0, 3}, {0, 2, 4}} → 2
- Use standard nested loops (row-major traversal).
- Check every individual cell.
- Increment a counter whenever the value is 0.
public int countZeros(int[][] grid) {
int count = 0;
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
if (grid[r][c] == 0) {
count++;
}
}
}
return count;
}- Using
grid.lengthfor the inner loop condition instead ofgrid[r].lengthorgrid[0].length. - Off-by-one loop errors (using
<=instead of<).
FRQ 2 — Row Sum
Write a method sumRow(int[][] grid, int row) that returns the sum of all elements in the specified row.
Row 1 of {{2, 5, 1}, {3, 4, 6}} → 3 + 4 + 6 = 13
- Because the row is fixed, you only need a single loop.
- Traverse all columns (
c) of the given row and add the values to a running total.
public int sumRow(int[][] grid, int row) {
int sum = 0;
for (int c = 0; c < grid[row].length; c++) {
sum += grid[row][c];
}
return sum;
}- Using a nested loop structure when only a single 1D array (one row) needs to be processed.
- Using
grid.lengthinstead ofgrid[row].lengthfor the boundary.
FRQ 3 — Column Sum
Write a method sumColumn(int[][] grid, int col) that returns the sum of all elements in the specified column.
Column 1 of {{1, 2}, {3, 4}} → 2 + 4 = 6
- Because the column is fixed, you only need a single loop.
- Loop through each row (
r) from 0 togrid.length. - Add the value at the fixed column index (
grid[r][col]) to the sum.
public int sumColumn(int[][] grid, int col) {
int sum = 0;
for (int r = 0; r < grid.length; r++) {
sum += grid[r][col];
}
return sum;
}- Looping over columns (
c < grid[0].length) instead of looping downward through the rows.
FRQ 4 — Count Even Numbers
Write a method countEvens(int[][] grid) that returns how many even numbers exist in the 2D array.
- Traverse every cell using a row-major nested loop.
- Check divisibility by 2 using the modulo operator (
% 2 == 0).
public int countEvens(int[][] grid) {
int count = 0;
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
if (grid[r][c] % 2 == 0) {
count++;
}
}
}
return count;
}- Using integer division (
/ 2) instead of modulo (% 2).
FRQ 5 — Find Maximum in the Grid
Write a method findMax(int[][] grid) that returns the largest integer value stored anywhere in the 2D array.
- Initialize a
maxvariable using the very first element of the grid (grid[0][0]). - Traverse all rows and columns with nested loops.
- Update
maxwhenever a strictly larger value is found.
public int findMax(int[][] grid) {
int max = grid[0][0];
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
if (grid[r][c] > max) {
max = grid[r][c];
}
}
}
return max;
}- Initializing
max = 0. If the entire grid contains only negative numbers,0will incorrectly be returned as the maximum. Always initialize withgrid[0][0].
FRQ 6 — Row With Largest Sum
Write a method rowWithLargestSum(int[][] grid) that returns the index of the row that produces the largest sum.
- Keep track of both the
maxSumand themaxRowindex. - Compute the sum for each row individually using an inner loop.
- Compare the completed row sum to
maxSumand update accordingly.
public int rowWithLargestSum(int[][] grid) {
int maxRow = 0;
int maxSum = Integer.MIN_VALUE;
for (int r = 0; r < grid.length; r++) {
int sum = 0;
for (int c = 0; c < grid[r].length; c++) {
sum += grid[r][c];
}
if (sum > maxSum) {
maxSum = sum;
maxRow = r;
}
}
return maxRow;
}- Forgetting to reset
int sum = 0;at the start of the outer row loop, causing the sum to continuously accumulate across the entire matrix. - Returning the
maxSumvalue instead of themaxRowindex.
FRQ 7 — Column With Smallest Sum
Write a method colWithSmallestSum(int[][] grid) that returns the index of the column with the smallest total sum.
- A natural approach is column-major traversal: let the outer loop iterate through the columns and the inner loop iterate through the rows.
- Keep a running total of the current column, then compare it to the overall
minSum.
public int colWithSmallestSum(int[][] grid) {
int minCol = 0;
int minSum = Integer.MAX_VALUE;
for (int c = 0; c < grid[0].length; c++) {
int sum = 0;
for (int r = 0; r < grid.length; r++) {
sum += grid[r][c];
}
if (sum < minSum) {
minSum = sum;
minCol = c;
}
}
return minCol;
}- Failing to swap the inner and outer loops. If the outer loop is rows, you cannot cleanly sum a complete column before moving on.
FRQ 8 — Replace Negatives With Zero
Write a method removeNegatives(int[][] grid) that mutates the array by replacing all negative values in the grid with 0.
- Traverse the grid using standard index-based nested loops.
- When a negative value is found, overwrite the specific index (
grid[r][c] = 0).
public void removeNegatives(int[][] grid) {
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
if (grid[r][c] < 0) {
grid[r][c] = 0;
}
}
}
}- Using an enhanced for-loop over the individual
intvalues and expecting assignments to change the actual array. - When modifying specific elements, use indexed access such as
grid[r][c]or modify through a row reference such asrow[c].
FRQ 9 — Scenario: Seating Chart Search
A classroom seating chart is represented by a 2D array of Strings. Write a method countTarget(String[][] chart, String target) that returns how many times the target student’s name appears. Note: Empty seats are represented by null.
- Traverse the grid using enhanced or standard loops.
- Critical AP Pattern: You must check if the current cell is
!= nullbefore calling.equals(target)to prevent aNullPointerException.
public int countTarget(String[][] chart, String target) {
int count = 0;
for (int r = 0; r < chart.length; r++) {
for (int c = 0; c < chart[0].length; c++) {
if (chart[r][c] != null && chart[r][c].equals(target)) {
count++;
}
}
}
return count;
}- Calling
.equals()directly on anullobject, which will immediately crash the program. Always check fornullfirst. - Using
==to compare Strings instead of.equals().
FRQ 10 — Scenario: Theater Seat Availability
A theater is represented by a 2D array of Seat objects. Write a method countAvailable(Seat[][] grid) that returns the total number of available seats. Assume the Seat class has a method public boolean isAvailable(). Some spaces in the grid may be walkways, represented by null.
- Because we only need to read data (not modify the grid or track specific indices), an enhanced for-loop is the cleanest approach.
- The outer loop grabs the 1D arrays (rows). The inner loop grabs the
Seatobjects.
public int countAvailable(Seat[][] grid) {
int count = 0;
for (Seat[] row : grid) {
for (Seat s : row) {
if (s != null && s.isAvailable()) {
count++;
}
}
}
return count;
}- Setting up the enhanced for-loop incorrectly. The outer variable must be a 1D array type (
Seat[]), not a singleSeat.
FRQ 11 — Check If Row Is Sorted
Write a method isRowSorted(int[][] grid, int row) that returns true if the specified row is sorted in strictly increasing order.
- Use a single loop to traverse the columns of the given row.
- Start the loop at
c = 1and compare the current elementgrid[row][c]to the previous elementgrid[row][c - 1]. - If order breaks, immediately return
false.
public boolean isRowSorted(int[][] grid, int row) {
for (int c = 1; c < grid[row].length; c++) {
if (grid[row][c] <= grid[row][c - 1]) {
return false; // Order broke
}
}
return true; // Loop finished without breaking
}- Starting the loop at
c = 0and checkingc - 1, resulting in an out-of-bounds error. - Returning
trueinside the loop immediately after a single valid comparison. You must check all elements before returningtrue.
FRQ 12 — Count Neighbors Greater Than a Value
Write a method countGreaterNeighbors(int[][] grid, int value) that returns how many cells have at least one neighbor (up, down, left, right) strictly greater than a given value.
- Traverse the grid. For each cell, check its four possible neighbors.
- Critical: You must verify the neighbor index is within the grid boundaries (e.g.,
r > 0) before attempting to read the neighbor’s value, utilizing Java’s short-circuit&&evaluation.
public int countGreaterNeighbors(int[][] grid, int value) {
int count = 0;
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
boolean found = false;
// Check UP
if (r > 0 && grid[r - 1][c] > value) found = true;
// Check DOWN
if (r < grid.length - 1 && grid[r + 1][c] > value) found = true;
// Check LEFT
if (c > 0 && grid[r][c - 1] > value) found = true;
// Check RIGHT
if (c < grid[r].length - 1 && grid[r][c + 1] > value) found = true;
if (found) count++;
}
}
return count;
}- Checking neighbors without validating boundaries, causing an immediate
ArrayIndexOutOfBoundsExceptionwhen evaluating cells on the edges of the matrix. - Incrementing
countmultiple times for a single cell if it has multiple valid neighbors. Use a boolean flag to ensure each cell is counted at most once.
FRQ 13 — Mirror Grid Horizontally
Write a method mirror(int[][] grid) that reverses each row of the grid in place.
- Loop down through all rows.
- For the inner loop, only loop halfway through the columns (
c < grid[r].length / 2). - Swap the element at index
cwith the element at indexlength - 1 - cusing a temporary variable.
public void mirror(int[][] grid) {
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length / 2; c++) {
int temp = grid[r][c];
grid[r][c] = gridr.length - 1 - c];
gridr.length - 1 - c] = temp;
}
}
}- Looping all the way to the end of the row. This reverses the row in the first half, and then perfectly undoes the reversal in the second half.
- Using the wrong index expression when finding the matching element from the other end of the row. The correct index is
grid[r].length - 1 - c.
FRQ 14 — Scenario: Count Increasing Columns
A weather station tracks daily temperatures across multiple cities in a 2D array. Write a method countIncreasingColumns(int[][] grid) that returns the number of columns in which every value is strictly greater than the value directly above it.
- This is a classic AP exam pattern requiring a column-major traversal. The outer loop iterates over the columns.
- Set a boolean flag
increasing = truefor the current column. - Loop downward through the rows starting at
r = 1, comparinggrid[r][c]to the value above it,grid[r - 1][c].
public int countIncreasingColumns(int[][] grid) {
int count = 0;
// Outer loop traverses columns
for (int c = 0; c < grid[0].length; c++) {
boolean increasing = true;
// Inner loop traverses rows downward
for (int r = 1; r < grid.length; r++) {
if (grid[r][c] <= grid[r - 1][c]) {
increasing = false;
}
}
if (increasing) {
count++;
}
}
return count;
}- Attempting a row-major traversal when vertical column tracking is explicitly required.
- Starting the inner row loop at
0and checkingr - 1, triggering an out-of-bounds error at the very top of the grid.
FRQ 15 — Scenario: Target in Every Row
A puzzle game board is represented by a 2D array. Write a method hasTargetInEveryRow(int[][] grid, int target) that returns true if every single row in the grid contains the target value at least once, and false otherwise.
- Set a boolean flag
rowHasTarget = falseat the start of every row. - Traverse across the row. If the target is found, set the flag to
true. - After finishing the row, if the flag is still
false, you know a row failed the condition, so immediately returnfalse.
public boolean hasTargetInEveryRow(int[][] grid, int target) {
for (int r = 0; r < grid.length; r++) {
boolean rowHasTarget = false;
for (int c = 0; c < grid[r].length; c++) {
if (grid[r][c] == target) {
rowHasTarget = true;
}
}
// If a row finishes and the target was never found
if (!rowHasTarget) {
return false;
}
}
// If we made it through all rows successfully
return true;
}- Returning
trueimmediately the moment the first target is found. This only confirms it exists in one row, not every row. You must check the entire grid before returningtrue.
Frequently Asked Questions
How do you traverse a 2D array in Java for the AP CSA exam?
To traverse a 2D array in standard row-major order, use nested for-loops. The outer loop iterates through the rows using grid.length, and the inner loop iterates through the columns of each row using grid[r].length or grid[0].length.
What is the difference between row-major and column-major traversal?
Row-major traversal processes a 2D array row by row, while column-major traversal processes it column by column. Students should understand how to recognize and implement these traversal patterns.
How do you find the sum of a specific row in a 2D array?
To sum a specific row, create a running total variable. Use a single loop to iterate through the columns of that specific row index using grid[row].length, adding each grid[row][c] value to your total.
What are the most common 2D array mistakes on the AP Computer Science A exam?
The most common mistakes are triggering an ArrayIndexOutOfBoundsException by incorrectly using grid.length for the inner column loop instead of grid[r].length, and forgetting to perform boundary checks (e.g., r > 0) before accessing neighboring elements.
Are these official College Board FRQs?
No. These are original, custom-designed AP CSA–style practice problems created for additional practice. They are not released College Board questions.
FRQ Strategy Tips for 2D Arrays (AP CSA)
- Know your bounds:
grid.lengthreturns the number of rows.grid[0].lengthreturns the number of columns. Do not mix them up. - Check neighbors safely: Always check if the index exists (e.g.,
c < grid[0].length - 1) before attempting to read a neighboring cell. - Single vs Nested Loops: If a question asks you to process an entire grid, you need nested loops. If a question asks you to process just one specific row or column, you only need one loop.
- When modifying values: Use indexed access such as
grid[r][c]when you need to change individual elements. An enhanced loop overintvalues gives you copies of those primitive values.
Related FRQ Pages
- Arrays – FRQ Practice
- ArrayList – FRQ Practice
- Strings – FRQ Practice
- Classes & Objects – FRQ Practice
- Mixed FRQs
- Mock FRQ Sets (Coming Soon)
Need Structured Help With AP Computer Science A?
If you want guided, one-on-one support for AP Computer Science A—including FRQs, MCQs, debugging, and exam strategy—you can explore my private AP CSA online tutoring program.
Ideal for students targeting a score of 4 or 5 on the AP CSA exam.
WhatsApp: +91 9853166385
Email: javatution@gmail.com
Book a free demo: Contact Chinmay