AlgoMaster Logo

Search a 2D Matrix II

mediumUpdated September 21, 2026

Understanding the Problem

We have a 2D matrix with a special structure: every row is sorted left to right, and every column is sorted top to bottom. We need to determine whether a given target value exists anywhere in this matrix.

This is different from LeetCode #74 (Search a 2D Matrix), where the first element of each row is greater than the last element of the previous row, effectively making the entire matrix one long sorted array. Here, that property does not hold. For instance, the first element of row 2 could be smaller than the last element of row 1. So we can't just flatten the matrix and do a single binary search.

The sorted-row and sorted-column properties give us a partial ordering across the matrix. The goal is to exploit that ordering so we avoid checking every cell.

Key Constraints:

  • 1 <= n, m <= 300 → The matrix has at most 300 x 300 = 90,000 cells. A brute force O(m * n) scan finishes well within typical limits, but the sorted structure lets us do far less work.
  • -10^9 <= matrix[i][j] <= 10^9 → Values can be negative, and they fit in a 32-bit signed integer, so comparisons need no special handling for overflow. We make no assumption about the sign of elements or the target.
  • Rows and columns are independently sorted → This is the property every efficient approach relies on. Moving right or down increases the value; moving left or up decreases it.

Approach 1: Brute Force

Intuition

Ignore the sorted properties and scan every cell. Loop through every row and column, compare each value against the target, and return true on the first match. If the scan reaches the end without a match, return false.

This is correct and a useful baseline, but it does no better than searching an unsorted matrix. The next approaches use the ordering to skip work.

Algorithm

  1. Iterate through every row of the matrix.
  2. For each row, iterate through every column.
  3. If the current cell equals the target, return true.
  4. If the loop ends without finding the target, return false.

Visualization and Code

Loading animation...

This approach works but ignores the sorted structure entirely. Since each row is sorted, we can use binary search within each row to skip cells much faster.

Approach 2: Binary Search per Row

Intuition

Each row is individually sorted in ascending order, so we can binary search a single row in O(log n) time instead of scanning it in O(n). Iterate through each row, run binary search on it, and return true if any row contains the target. If no row contains it, the target is absent.

One optimization avoids wasted searches. Because each row is sorted, its first element is the row minimum and its last element is the row maximum. If the target is smaller than the first element or larger than the last, it cannot be in that row, so we skip it before binary searching.

Algorithm

  1. For each row in the matrix:
    • If the target is less than the first element of this row, skip it.
    • If the target is greater than the last element of this row, skip it.
    • Otherwise, run binary search on this row.
    • If binary search finds the target, return true.
  2. If no row contains the target, return false.

Visualization and Code

Loading animation...

This uses the row-sorted property but ignores the column-sorted property. The next approach uses both at once, letting a single comparison eliminate an entire row or column.

Approach 3: Staircase Search (Optimal)

Intuition

The starting position determines whether comparisons are useful. From the top-left corner, both moving right and moving down increase the value, so a cell smaller than the target gives no information about which direction to go. The bottom-right corner has the mirror problem: both directions decrease.

The top-right corner avoids this. From position (0, n-1):

  • Moving left decreases the value (rows are sorted left to right).
  • Moving down increases the value (columns are sorted top to bottom).

Every comparison now points one way. If the current value is larger than the target, move left to eliminate the current column. If it is smaller, move down to eliminate the current row. Each step removes one row or one column, so the search finishes in at most m + n steps.

Algorithm

  1. Start at the top-right corner: row = 0, col = n - 1.
  2. While row is within bounds and col is within bounds:
    • If matrix[row][col] equals the target, return true.
    • If matrix[row][col] is greater than the target, move left (col--). This eliminates the current column.
    • If matrix[row][col] is less than the target, move down (row++). This eliminates the current row.
  3. If we go out of bounds without finding the target, return false.

Visualization and Code

Loading animation...