Computer Science A
FRQ - 2D Arrays
Introduction to 2D Array Questions on AP CSA FRQs
Overview
2D Arrays are a common topic in the AP Computer Science A exam, appearing frequently in the Free-Response Question (FRQ) section. These questions test your ability to manipulate nested data structures and demonstrate core concepts of iteration, indexing, and logical problem-solving.
2D Arrays represent grid-like data structures (like tables or matrices) and are widely used to solve problems related to game boards, seating charts, or pixel manipulation in images.
Demographics of 2D Array Questions
Frequency
- Typically, one FRQ per year focuses heavily on 2D arrays or uses them as part of the solution.
- Recent FRQs (from 2019–2023) include 2D array questions testing nested loops and problem-solving within a grid structure.
Scoring Patterns
- Students often secure basic setup points (e.g., correctly declaring/initializing a 2D array or accessing elements).
- The most missed points are in loop logic, particularly handling boundary conditions (e.g., avoiding
ArrayIndexOutOfBoundsException).
Common Student Errors
- Misusing row and column indices (
array[row][col]vs.array[col][row]). - Forgetting that a 2D array is an array of arrays, leading to confusion about its length (
array.lengthfor rows,array[0].lengthfor columns).
How 2D Array FRQs Are Typically Formatted
Part (a): Basic Access and Manipulation
- Common Tasks:
- Traverse the array using nested loops.
- Return a value from a specific row/column or based on conditions (e.g., count all
truevalues).
- Tips to Ensure Points:
- Properly initialize variables.
- Use correct indexing:
array[i][j]. - Ensure loops iterate through the correct dimensions (
rowandcolumnlengths).
// Example: Traversing a 2D Array
int[][] array = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
for (int row = 0; row < array.length; row++) {
for (int col = 0; col < array[row].length; col++) {
System.out.print(array[row][col] + " ");
}
System.out.println(); // Print a new line after each row
}
2021 FRQ Question 4
This question involves manipulating a two-dimensional array of integers. You will write two static methods of the ArrayResizer class, which is shown below.
public class ArrayResizer
{
/**
* Returns true if and only if every value in row r of array2D is non-zero.
* Precondition: r is a valid row index in array2D.
* Postcondition: array2D is unchanged.
*/
public static boolean isNonZeroRow(int[][] array2D, int r)
{ /* to be implemented in part (a) */ }
/**
* Returns the number of rows in array2D that contain all non-zero values.
* Postcondition: array2D is unchanged.
*/
public static int numNonZeroRows(int[][] array2D)
{ /* implementation not shown */ }
/**
* Returns a new, possibly smaller, two-dimensional array that contains only rows
* from array2D with no zeros, as described in part (b).
* Precondition: array2D contains at least one column and at least one row with no zeros.
* Postcondition: array2D is unchanged.
*/
public static int[][] resize(int[][] array2D)
{ /* to be implemented in part (b) */ }
}
## Part (a) and Part (b) Combined
### (a) Write the `isNonZeroRow` method
Write the method `isNonZeroRow`, which returns `true` if and only if all elements in row `r` of a two-dimensional array `array2D` are not equal to zero.
For example, consider the following statement, which initializes a two-dimensional array:
<!-- -->
```java
int[][] arr = {
{2, 1, 0},
{1, 3, 2},
{0, 0, 0},
{4, 5, 6}
};
Sample calls to isNonZeroRow are shown below:
Call to isNonZeroRow |
Value Returned | Explanation |
|---|---|---|
ArrayResizer.isNonZeroRow(arr, 0) |
false |
At least one value in row 0 is zero. |
ArrayResizer.isNonZeroRow(arr, 1) |
true |
All values in row 1 are non-zero. |
ArrayResizer.isNonZeroRow(arr, 2) |
false |
At least one value in row 2 is zero. |
ArrayResizer.isNonZeroRow(arr, 3) |
true |
All values in row 3 are non-zero. |
Complete the isNonZeroRow method:
/** Returns true if and only if every value in row r of array2D is non-zero.
* Precondition: r is a valid row index in array2D.
* Postcondition: array2D is unchanged.
*/
public static boolean isNonZeroRow(int[][] array2D, int r)
{
// Your implementation here
}
(b) Write the resize method
Write the method resize, which returns a new two-dimensional array containing only rows from array2D with all non-zero values. The elements in the new array should appear in the same order as the order in which they appeared in the original array.
The following code segment initializes a two-dimensional array and calls the resize method:
int[][] arr = {
{2, 1, 0},
{1, 3, 2},
{0, 0, 0},
{4, 5, 6}
};
int[][] smaller = ArrayResizer.resize(arr);
When the code segment completes, the following will be the contents of smaller:
{
{1, 3, 2},
{4, 5, 6}
}
A helper method, numNonZeroRows, has been provided for you. The method returns the number of rows in its two-dimensional array parameter that contain no zero values.
Complete the resize method. Assume that isNonZeroRow works as specified, regardless of what you wrote in part (a). You must use numNonZeroRows and isNonZeroRow appropriately to receive full credit.
/** Returns a new, possibly smaller, two-dimensional array that contains only rows
* from array2D with no zeros, as described in part (b).
* Precondition: array2D contains at least one column and at least one row with no zeros.
* Postcondition: array2D is unchanged.
*/
public static int[][] resize(int[][] array2D)
{
// Your implementation here
}
AP® Computer Science A 2021 Scoring Guidelines
Question 4: 2D Array (9 points)
Canonical Solution
(a)
public static boolean isNonZeroRow(int[][] array2D, int r) {
for (int col = 0; col < array2D[0].length; col++) {
if (array2D[r][col] == 0) {
return false;
}
}
return true;
}
(b)
public static int[][] resize(int[][] array2D) {
int numRows = array2D.length;
int numCols = array2D[0].length;
int[][] result = new int[numNonZeroRows(array2D)][numCols];
int newRowIndex = 0;
for (int r = 0; r < numRows; r++) {
if (isNonZeroRow(array2D, r)) {
for (int c = 0; c < numCols; c++) {
result[newRowIndex][c] = array2D[r][c];
}
newRowIndex++;
}
}
return result;
}
(a) isNonZeroRow Scoring Criteria
| Scoring Criteria | Decision Rules |
|---|---|
1 Compares an item from array2D with 0 |
Responses will not earn the point if they fail to attempt the comparison, even if they access an item from array2D. 1 point |
2 Accesses every item from row r of 2D array (no bounds errors) |
Responses can still earn the point even if they return early from an otherwise correctly-bounded loop. 1 point |
3 Returns true if and only if row contains no zeros |
Responses can still earn the point even if they process a column of the 2D array rather than a row. Responses will not earn the point if they fail to return a value in some cases. 1 point |
Total for part (a): 3 points
(b) resize Scoring Criteria
| Scoring Criteria | Decision Rules |
|---|---|
4 Calls numNonZeroRows and isNonZeroRow |
Responses can still earn the point even if they fail to use or store the return value. Responses will not earn the point if they include incorrect number or type of parameters or call methods on an object or class other than ArrayResizer. 1 point |
5 Identifies rows with no zeros (in the context of an if) |
Responses can still earn the point even if they call isNonZeroRow incorrectly, if the row being tested is clearly identified (index or reference). 1 point |
| 6 Declares and creates a new 2D array of the correct size | Response will not earn the point if they transpose the dimensions of the created array. 1 point |
| 7 Maintains an index in the new array | Responses will not earn the point if they fail to declare, initialize, and update a different index or maintain the index in a way that overwrites, skips, or duplicates rows. 1 point |
8 Traverses all necessary elements of array2D (no bounds errors) |
Responses can still earn the point even if they cause a bounds error by declaring and creating a new 2D array of incorrect size or fail to maintain an index in the new array correctly, resulting in a bounds error. Responses will not earn the point if they transpose coordinates, leading to a bounds error and/or copying columns. 1 point |
| 9 Copies all and only rows identified as having no zero elements into the new array | Responses can still earn the point even if they copy a reference, identify rows incorrectly (if the logical sense can be determined and is correct), or copy columns instead of rows, consistent with the dimensions of the created 2D array. Responses will not earn the point if they remove or overwrite data from array2D (instead of or in addition to copying it to the new array) or reverse the logical sense of which rows to copy. 1 point |
Total for part (b): 6 points
Question-Specific Penalties
- -1 (u) Use
array2D[].lengthto refer to the number of columns in a row of the 2D array.
Total for question 4: 9 points
Easy Points for AP® CSA 2021 FRQ Question 4
Part (a): isNonZeroRow (3 Points Total)
- Compare an element to
0✅- Example:
if (array2D[r][col] == 0)
- Example:
- Loop through all columns without bounds errors ✅
- Example:
for (int col = 0; col < array2D[0].length; col++)
- Example:
- Return
trueorfalsecorrectly ✅- Example:
return false;when0is found.
- Example:
Part (b): resize (6 Points Total)
- Call
isNonZeroRowornumNonZeroRows✅- Example:
if (isNonZeroRow(array2D, r))
- Example:
- Use an
ifstatement to identify rows with no0s ✅- Example:
if (isNonZeroRow(array2D, r))
- Example:
- Create a new 2D array with the correct dimensions ✅
- Example:
int[][] result = new int[numRows][numCols];
- Example:
Sample Problem 2 - Competition!
For this problem, please listen to instructions. There will be an in-class competition which will be an opportunity for extra credit. However, you must complete this problem either way as part of the homework.
Problem
This question involves a path through a two-dimensional (2D) array of integers, where the path is based on the values of elements in the array. When an element of the 2D array is accessed, the first index is used to specify the row and the second index is used to specify the column. The following Location class represents a row and column position in the 2D array.
// Run this code cell so that using the location class doesn't throw errors in future code cells!
public class Location {
private int theRow;
private int theCol;
public Location(int r, int c) {
theRow = r;
theCol = c;
}
public int getRow() {
return theRow;
}
public int getCol() {
return theCol;
}
}
The following GridPath class (see the next code cell) contains the 2D array and methods to use to determine a path through the array. You will write two methods of the GridPath class.
(a) Write the getNextLoc method, which returns a Location object that represents the smaller of two neighbors of the grid element at row and col, according to the following rules.
- The two neighbors that are considered are the element below the given element and the element to the right of the given element, if they exist.
- If both neighbors exist, the Location of the neighbor with the smaller value is returned. Two neighbors will always have different values.
- If only one neighbor exists, the Location of the existing neighbor is returned.
For example, assume that the grid contains the following values:

The following table shows some sample calls to getNextLoc.
| Method Call | Explanation |
|---|---|
getNextLoc(0, 0) |
Returns the neighbor to the right (the Location representing the element at row 0 and column 1), since 3 < 11 |
getNextLoc(1, 3) |
Returns the neighbor below (the Location representing the element at row 2 and column 3), since 15 < 16 |
getNextLoc(2, 4) |
Returns the neighbor below (the Location representing the element at row 3 and column 4), since the given element has no neighbor to the right |
getNextLoc(4, 3) |
Returns the neighbor to the right (the Location representing the element at row 4 and column 4), since the given element has no neighbor below |
In the example, the getNextLoc method will never be called with row 4 and column 4, as
those values would violate the precondition of the method.
(b) Write the sumPath method, which returns the sum of all values on a path in grid. The path
begins with the element at row and col and is determined by successive calls to getNextLoc.
The path ends when the element in the last row and the last column of grid is reached.
For example, consider the following contents of grid. The shaded elements of grid represent the
values on the path that results from the method call sumPath(1, 1). The method call returns 19
because 3 + 1 + 2 + 1 + 9 + 1 + 4 + 1 + 0 + 1 + 1 + 5 = 19.

```java public class GridPath { /** Initialized in the constructor with distinct values that never change */ private int[][] grid;
public GridPath(int[][] values)
{
grid = values;
}
/**
* Returns the Location representing a neighbor of the grid element at row and col,
* as described in part (a)
* Preconditions: row is a valid row index and col is a valid column index in grid.
* row and col do not specify the element in the last row and last column of grid.
*/
public Location getNextLoc(int row, int col) {
/* to be implemented in part (a) */
}
/**
* Computes and returns the sum of all values on a path through grid, as described in
* part (b)
* Preconditions: row is a valid row index and col is a valid column index in grid.
* row and col do not specify the element in the last row and last column of grid.
*/
public int sumPath(int row, int col) {
/* to be implemented in part (b) */
}
// There may be instance variables, constructors, and methods that are not shown. }