Arrays · Matrix Techniques

Matrix Binary Search

Treating a row-major-sorted 2D grid as a single sorted 1D array via index math, so plain binary search applies without ever materializing that flattened array.

  • 6 min read
  • 11 practice questions
  • 2 graded problems
On this page
  1. Description
  2. The approach
  3. A second flavor: staircase search from a corner
  4. Where you'll see it
  5. Which tool for which job?
  6. Common mistakes
  7. Check yourself
  8. Key takeaways
  9. Quick revise
  10. Practice

Description

Matrix binary search finds a value in a sorted grid without checking every cell. Which method works depends on how the grid is sorted. If it reads as one sorted sequence, row after row, binary search it like a flat array and convert each index to a row and a column. If each row and each column is only sorted on its own, walk a staircase from a corner, ruling out a whole row or column at every step.

We'll go from simple to more technical:

  1. The pattern: binary search over a flat index.
  2. A second flavor: staircase search from the top-right corner.
  3. Where virtual indexes and two-way-sorted structures show up in production.
  4. Matching the method to the guarantee the matrix actually gives.

The approach

Checking every cell takes O(rows x cols). But suppose each row starts where the row above ended, so the whole grid reads as one sorted list. Then number the cells 0, 1, 2, and so on, row by row, and binary search those numbers. Cell number i is at row i / cols and column i % cols. You never build the flat list; you only convert numbers.

Searching for 20 in a grid with 4 columns:

Column 0Column 1Column 2Column 3
Row 025811
Row 114172023
Row 226293235
lohimidCell (mid / 4, mid % 4)ValueMove
0115(1, 1)17too small: lo = 6
6118(2, 0)26too big: hi = 7
676(1, 2)20found

Java

int lo = 0, hi = rows * cols - 1;
while (lo <= hi) {
    int mid = lo + (hi - lo) / 2;
    int value = matrix[mid / cols][mid % cols];   // flat index -> (row, col)
    if (value == target) return true;
    if (value < target) lo = mid + 1;
    else hi = mid - 1;
}
return false;

Python

def search(matrix: list[list[int]], target: int) -> bool:
    rows, cols = len(matrix), len(matrix[0])
    lo, hi = 0, rows * cols - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        value = matrix[mid // cols][mid % cols]   # flat index -> (row, col)
        if value == target:
            return True
        if value < target:
            lo = mid + 1
        else:
            hi = mid - 1
    return False

A second flavor: staircase search from a corner

A weaker guarantee is more common. Each row is sorted left to right and each column top to bottom. But a row may start with a smaller value than the row above ended with. Flat binary search fails here, because the grid no longer reads as one sorted list. Start at the top-right corner instead. Moving left makes values smaller, and moving down makes them bigger. So one comparison tells you which way to go, and each step rules out a whole row or column.

Searching for 11 in this grid, where row 0 ends at 14 but row 1 starts at 5:

Column 0Column 1Column 2Column 3
Row 0361014
Row 1591218
Row 28111521

The walk visits 14 (too big: go left), 10 (too small: go down), 12 (too big: left), 9 (too small: down), then finds 11.

Java

int row = 0, col = cols - 1;   // top-right corner
while (row < rows && col >= 0) {
    int value = matrix[row][col];
    if (value == target) return true;
    if (value > target) col--;   // eliminate this whole column
    else row++;                  // eliminate this whole row
}
return false;

Python

def search(matrix: list[list[int]], target: int) -> bool:
    rows, cols = len(matrix), len(matrix[0])
    row, col = 0, cols - 1            # top-right corner
    while row < rows and col >= 0:
        value = matrix[row][col]
        if value == target:
            return True
        if value > target:
            col -= 1                  # eliminate this whole column
        else:
            row += 1                  # eliminate this whole row
    return False

The corner matters. From the top-left, moving down and moving right both make values bigger. No comparison can tell you which way is safe, so the walk doesn't work from there.

Where you'll see it

A sorted sequence is often stored in pieces: pages of results, or fixed-size blocks on disk. You can still binary search it by turning a position in the sequence into "which block, and where in it", the same conversion as row and column. That avoids building a merged copy first.

Which tool for which job?

You needUse
Search a matrix that's sorted as one sequencebinary search on a flat index: (i / cols, i % cols)
Search when rows and columns are sorted separatelystaircase from the top-right (or bottom-left)
Very few rows, very long rowsbinary search each row, O(rows log cols)
Count values ≤ xa staircase walk, O(rows + cols)
The k-th smallestbinary search on the value, counting with the staircase
Bisect in Python without copyinga small class with __len__ and __getitem__

Common mistakes

MistakeWhat happensDo this instead
Flat binary search on a row-and-column-sorted matrixmisses values that are therestaircase search
Staircase from the top-left or bottom-rightboth moves increase (or decrease) - no safe stepstart top-right or bottom-left
Dividing the flat index by rowsthe wrong celldivide and take the remainder by cols
rows * cols as a Java intoverflow for big gridscompute the size in long
Flattening into a copy firstO(rows x cols) time and memoryindex the matrix directly

Check yourself

Try to answer before opening each one - recalling beats re-reading.

1. Each row and each column is sorted, but row 2's first value is smaller than row 1's last. Can you use flat binary search?

Show answer

No. Flat binary search needs the whole grid to read as one sorted list, row after row, and this grid doesn't. It's a different problem: use the staircase walk, which only needs each row and column sorted on its own.

2. Why does the staircase start at the top-right corner rather than the top-left?

Show answer

At the top-right, moving left makes values smaller and moving down makes them bigger. Comparing with the target tells you which way to go, and so which row or column to rule out. At the top-left, both moves make values bigger, so no comparison gives a safe step.

3. A grid has 2 rows and 3 columns. Which cell is flat index 4?

Show answer

Row 4 / 3 = 1, column 4 % 3 = 1, so matrix[1][1]. Divide and take the remainder by the number of columns, not rows.

Key takeaways

  • A grid that reads as one sorted list can be binary searched through a flat index: row i / cols, column i % cols. That's O(log(rows x cols)).
  • A grid sorted only by row and by column needs the staircase walk, O(rows + cols).
  • Start the staircase at the top-right or bottom-left, where the two moves change the value in opposite directions.
  • Check which sort guarantee the grid really has before choosing a method.

Quick revise

The whole skill on one page, for the night before an interview.

Everything from the lesson and the deep dive on one page. Skim it before practice or an interview, and open the full lesson for anything that doesn't ring a bell.

Pick the tool

You needUse
Globally sorted matrixflat-index binary search
Rows and columns sortedstaircase from top-right
Few long rowsbinary search each row
Count ≤ xstaircase from bottom-left
k-th smallestbinary search on value + count

Snippets worth knowing by heart

Java

long lo = 0, hi = (long) rows * cols - 1;            // long: no overflow
while (lo <= hi) {
    long mid = lo + (hi - lo) / 2;
    int v = m[(int) (mid / cols)][(int) (mid % cols)];   // divide by cols
    if (v == target) return true;
    if (v < target) lo = mid + 1; else hi = mid - 1;
}
return false;

Python

r, c = 0, len(m[0]) - 1          # top-right corner
while r < len(m) and c >= 0:
    if m[r][c] == target:
        return True
    if m[r][c] > target:
        c -= 1                   # this column is too big from here down
    else:
        r += 1                   # this row is too small from here left
return False

The traps

  • Flat search on a row-and-column-sorted matrix: rows don't continue each other, so values are missed. Use the staircase search.
  • The wrong corner: from top-left both moves increase, so no step is safe. Start top-right or bottom-left.
  • Dividing by rows: the flat index maps to the wrong cell. Divide and take the remainder by cols.
  • rows * cols as an int: big grids overflow. Compute the size in long.
  • Copying to flatten: it costs O(rows x cols) time and memory. Index the matrix directly.

Staff-level points, one line each

  • Staircase invariant: the target, if present, is in what's left; at most rows + cols steps.
  • 10 x 100,000: 100,000 staircase steps vs 170 per-row binary-search probes.
  • k-th smallest: binary search on value, staircase count - matched sorting.
  • 50,000 x 50,000 as an int is -1794967296.
  • Python's bisect works on a __getitem__ wrapper - no copy.

Say it in an interview

  • "The matrix reads as one sorted array, so I binary search a flat index."
  • "With rows and columns sorted separately, I start top-right and drop a row or column each step."
  • "That's O(rows + cols); if one side were tiny I'd binary search each row instead."
  • "I never flatten it into a copy."

Practice

This skill comes with 11 multiple-choice questions that tell you which misconception a wrong answer reveals and 2 graded problems. Your answers are graded and your mastery is tracked, so you'll know when the skill holds up. Running code and saving progress need a free account.

Practice Matrix Binary Search free

Search a 2D Matrix

MediumProCoding problemJava · Python

Each row of the matrix is sorted, and each row starts above the previous row's last value, so reading the matrix row by row gives one sorted list. Return whether target is in it.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Search a 2D Matrix II

MediumProCoding problemJava · Python

Every row of this matrix increases from left to right, and every column increases from top to bottom. Unlike a fully sorted matrix, a row can start lower than the previous row ends. Return whether target is in it.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Practice Matrix Binary Search free

No card needed. Lessons, practice questions and easy problems are free forever.

Free plan, no card · 7-day Pro trial · Cancel anytime