Free for students · Ad-free · WCAG 2.1 AA Compliant · Accessibility

Implementing 2D Array Algorithms

Lesson ~10 min read 8 MCQs

In simple terms: In simple terms, this topic is about writing code to perform common tasks on 2D arrays, like finding the highest value, calculating totals, or shifting elements around in a grid.

Why this matters

Imagine you're helping run the concession stand for the school's basketball team. You track sales in a spreadsheet: rows are for different snacks (popcorn, pretzels, soda), and columns are for each quarter of the game. At the end of the night, you need answers. What was our best-selling item? How much money did we make in the 4th quarter? Did any item sell out completely?

A 2D array is just like that spreadsheet. It's a grid for organizing information. Knowing how to write algorithms for 2D arrays lets you answer all those questions and more. You're not just storing data; you're making sense of it. Today, we'll break down the standard "recipes"—the algorithms—for pulling powerful insights from these data grids.

A 2D array as a concession stand spreadsheet.

Concept overview

flowchart TD
    A[Start] --> B{Initialize maxVal = grid[0][0]};
    B --> C{For each row 'r' in grid};
    C --> D{For each column 'c' in grid[r]};
    D --> E{Is grid[r][c] > maxVal?};
    E -- Yes --> F{maxVal = grid[r][c]};
    E -- No --> G[Next column];
    F --> G;
    G --> D;
    D -- End of Row --> H[Next row];
    H --> C;
    C -- End of Grid --> I[Return maxVal];
    I --> J[End];
This is a flowchart diagram illustrating the algorithm to find the maximum value in a 2D array. The process starts by initializing a max variable with the first element, then uses nested loops to traverse every element, updating the max variable whenever a larger value is found. The final step is to return the max variable after the loops complete.

Core explanation

You've learned how to create and traverse 2D arrays. Now, let's put them to work. An algorithm is just a set of steps to solve a problem. For 2D arrays, most algorithms involve a nested loop to visit every element, but what you do inside that loop is what matters.

Let's use a great analogy: a 2D array is like a digital spreadsheet. The rows and columns are just like in Excel. The algorithms we'll write are like creating our own SUM(), MAX(), or COUNTIF() functions.

Aggregations: Sum, Average, Min & Max

These algorithms "boil down" the entire grid (or a part of it) into a single number. They all follow a similar pattern:

  1. 1
    Initialize
    a variable to hold your result.
  2. 2
    Traverse
    the array (or the specific row/column) with nested loops.
  3. 3
    Update
    your variable at each element.
  4. 4
    Return
    the final result after the loops finish.

Finding a Sum or Average

Let's say we have a 2D array of integers representing weekly sales for different products at a farmer's market in Dallas.

int[][] weeklySales = {
  {150, 200, 160, 210}, // Product A
  {120, 130, 140, 125}, // Product B
  {180, 190, 220, 240}  // Product C
};

To find the total sales of all products, we sum every element.

Tracing the `getTotalSales` method for a 2D array.
public static int getTotalSales(int[][] sales) {
  int total = 0; // 1. Initialize
  for (int r = 0; r < sales.length; r++) {
    for (int c = 0; c < sales[0].length; c++) {
      total += sales[r][c]; // 3. Update
    }
  }
  return total; // 4. Return
}

To find the average, you'd do the same thing, but at the end, divide by the total number of elements: sales.length * sales[0].length.

What if you only want the sum for a specific row (e.g., total sales for Product B, which is row 1)? You just use a single loop for that row's columns.

public static int getRowSum(int[][] sales, int row) {
  int rowTotal = 0;
  // Note: We only loop through the columns of the specified row
  for (int c = 0; c < sales[row].length; c++) {
    rowTotal += sales[row][c];
  }
  return rowTotal;
}

Finding the Minimum or Maximum

This is almost identical, but the update step is a comparison. To find the highest sale amount in the whole grid:

public static int getMaximumSale(int[][] sales) {
  // 1. Initialize with the VERY FIRST element.
  int maxVal = sales[0][0];
  for (int r = 0; r < sales.length; r++) {
    for (int c = 0; c < sales[0].length; c++) {
      // 3. Update if we find a bigger value
      if (sales[r][c] > maxVal) {
        maxVal = sales[r][c];
      }
    }
  }
  return maxVal; // 4. Return
}

Property Checks: Counting and Searching

These algorithms check elements against a certain condition.

  • Count how many elements have a property.
  • Determine if at least one element has a property.
  • Determine if all elements have a property.

Let's imagine a boolean[][] grid representing a tic-tac-toe board, where true means 'X' is in that spot.

Counting Elements with a Property

How many 'X's are on the board? This is just like finding a sum, but we add 1 instead of the element's value.

public static int countXs(boolean[][] board) {
  int count = 0;
  for (int r = 0; r < board.length; r++) {
    for (int c = 0; c < board[0].length; c++) {
      if (board[r][c] == true) { // The property check
        count++;
      }
    }
  }
  return count;
}

Finding "At Least One"

Does the board have at least one 'X'? You can stop searching as soon as you find one.

public static boolean hasAtLeastOneX(boolean[][] board) {
  for (int r = 0; r < board.length; r++) {
    for (int c = 0; c < board[0].length; c++) {
      if (board[r][c] == true) {
        return true; // Found one! Exit immediately.
      }
    }
  }
  // If we get here, the loops finished without finding any.
  return false;
}

Determining if "All" Have a Property

This one is tricky. The logic is inverted. You assume the property is true for all elements, and you search for a single counterexample that proves you wrong.

Let's say we have an array of test scores and want to see if every student in a particular class (row) passed (scored >= 60).

public static boolean allPassedInRow(int[][] scores, int row) {
  for (int c = 0; c < scores[row].length; c++) {
    if (scores[row][c] < 60) {
      // Found a failing score. We can immediately say they didn't ALL pass.
      return false;
    }
  }
  // If the loop completes without finding any failing scores, then they all passed.
  return true;
}

Positional and Structural Algorithms

These algorithms care about the position of elements relative to each other.

Accessing Consecutive Pairs

To check for adjacent identical numbers in a row, you compare grid[r][c] with grid[r][c+1]. The key is to stop your column loop one step early to avoid an ArrayIndexOutOfBoundsException.

// Check for any adjacent duplicates in a single row
for (int c = 0; c < grid[row].length - 1; c++) { // Notice the "- 1"
  if (grid[row][c] == grid[row][c+1]) {
    System.out.println("Found a pair!");
  }
}

Finding Duplicates

To find if there are any duplicate values in the entire 2D array, a common (though not the most efficient) approach is to use nested loops to compare every element to every other element. This is a bit more complex, often involving four nested loops. The AP exam is more likely to ask you to find duplicates within a single row or column.

Shifting and Rotating

This is a classic AP problem. Let's shift a row to the left. The element at index 0 is lost, grid[r][1] moves to grid[r][0], grid[r][2] moves to grid[r][1], and so on.

public static void shiftRowLeft(int[] row) {
  // To rotate, you'd save this value first: int first = row[0];
  for (int c = 0; c < row.length - 1; c++) {
    row[c] = row[c + 1];
  }
  // The last element can be set to 0 or some other default.
  // If rotating, you'd set it to the saved 'first' value.
  row[row.length - 1] = 0;
}

To use this on a 2D array, you'd pass myGrid[someRow] to this method.

Reversing a Row or Column

To reverse a row, you swap the first and last elements, then the second and second-to-last, and so on, until you meet in the middle. This is often called the "two-pointer" technique.

public static void reverseRow(int[] row) {
  int start = 0;
  int end = row.length - 1;

  while (start < end) {
    // Swap the elements
    int temp = row[start];
    row[start] = row[end];
    row[end] = temp;

    // Move the pointers
    start++;
    end--;
  }
}

These standard algorithms are your toolkit. The AP exam will test you by asking you to implement them directly or to combine them to solve a slightly new problem. Practice them until the patterns feel second nature.

Tracing `getRowSum` for a specific row (Product B, row 1).
Tracing `getMaximumSale` to find the highest value in the grid.

See it in action

Code

    
Memory
Variables
Step 0 / 0

Worked examples

Let's walk through a few problems to see these algorithms in action. The key is to break down the problem and identify which pattern to use.

Example 1

Finding the Highest Score in a Column

Problem: You have a 2D array gradebook where rows represent students and columns represent assignments. The columns are: Homework 1, Homework 2, Midterm, Final Exam. Find the highest score achieved by any student on the Final Exam (column index 3).

int[][] gradebook = {
  {90, 95, 88, 92},  // Student 0: Priya
  {75, 80, 78, 85},  // Student 1: Carlos
  {100, 98, 95, 99}  // Student 2: Aaliyah
};
int finalExamCol = 3;

Solution Walkthrough:

  1. 1
    Identify the Goal
    We need to find the maximum value, but only within a specific column. This is a "Max" algorithm on a subsection of the array.
  2. 2
    Choose the Algorithm
    We'll use the find-maximum pattern. We need to loop, but instead of nested loops for the whole grid, we'll loop down the rows, keeping the column index fixed.
  3. 3
    Initialize
    We need a variable to store the maximum score. The safest way is to initialize it with the first value we'll check: the score in the first student's final exam column. int maxScore = gradebook[0][finalExamCol]; // This is 92.
  4. 4
    Loop and Compare
    Now, we'll loop through the rest of the students (rows) and compare their final exam score to our current maxScore.
    • Start the loop at r = 1 because we already used r = 0 to initialize.
    • Iteration r = 1 (Carlos): Is gradebook[1][3] (which is 85) greater than maxScore (92)? No. maxScore remains 92.
    • Iteration r = 2 (Aaliyah): Is gradebook[2][3] (which is 99) greater than maxScore (92)? Yes. We update maxScore to 99.
Tracing `getHighestInColumn` for the Final Exam column (index 3).
  1. Final Result: The loop finishes. The final value of maxScore is 99.

Code:

public int getHighestInColumn(int[][] grades, int col) {
  // Handle empty array case to be robust
  if (grades.length == 0) return -1; // Or throw an exception

  int maxScore = grades[0][col]; // Initialize with the first row's value in that col
  for (int r = 1; r < grades.length; r++) {
    if (grades[r][col] > maxScore) {
      maxScore = grades[r][col];
    }
  }
  return maxScore;
}
Example 2

Shifting a Row for a Seating Chart

Problem: A theater in Chicago has a seating chart represented by a 2D array of strings. An usher needs to ask an entire row of patrons to shift one seat to the right to make space for a wheelchair. The person in the last seat moves out of the row. The first seat becomes empty. Write a method to do this for a given row.

Solution Walkthrough:

  1. 1
    Identify the Goal
    We need to shift all elements in a single row one position to the right. This is a positional algorithm.
  2. 2
    The Trap
    If you start at the beginning of the row and copy row[0] to row[1], you've just overwritten the value that was supposed to go into row[2]!
    • row[1] = row[0];
    • row[2] = row[1]; // Oops! row[1] is now the same as row[0].
  3. 3
    Do This Instead
    To avoid overwriting values you still need, you must start from the end of the row and work backwards.
  4. 4
    Loop and Copy
    • The value at row[length - 2] goes into row[length - 1].
    • The value at row[length - 3] goes into row[length - 2].
    • ...and so on, until the value at row[0] goes into row[1].
  5. 5
    Handle the First Seat
    After the loop, the first seat (row[0]) needs to be set to "empty".

Code:

public void shiftRowRight(String[] row) {
  // Start from the second-to-last element and go down to the first.
  for (int i = row.length - 1; i > 0; i--) {
    row[i] = row[i - 1]; // Copy the element from the left into the current spot.
  }
  // Now, clear the first seat.
  row[0] = "empty";
}

This is a crucial pattern. For shifts, think about which direction you need to loop from to avoid destroying data you haven't processed yet. For a right shift, loop from the right. For a left shift, loop from the left.

Choosing the right loop structure for 2D array problems.

Try it yourself

Ready to try a couple on your own? Don't worry about writing a full program, just focus on the logic for the method itself.

Problem 1: The Vending Machine

You're given a 2D integer array inventory where each cell represents the quantity of a snack in a vending machine in Seattle. Write a method isAnythingSoldOut(int[][] inventory) that returns true if any snack has a quantity of 0, and false otherwise.

Hint: This is an "at least one" algorithm. What does that mean for your loops? Can you stop early?

Problem 2: Reversing a Column

You're given a 2D array gameBoard. Write a method reverseColumn(String[][] gameBoard, int col) that reverses the order of the elements in a specified column. For example, the element at the top of the column should swap with the element at the bottom, and so on.

Hint: This is very similar to reversing a 1D array. Use the two-pointer technique (a top index starting at 0, a bottom index starting at the last row). What will your while loop condition be? Remember to use a temporary variable for swapping.

Visualizing the `reverseColumn` problem with a game board.