Search a 2D Matrix
Read row by row, the grid is one sorted array of length m · n. We do not need to build that array. Give each cell a number idx from 0 to m·n − 1 in reading order. Since every row has n cells, cell idx is at row idx / n, column idx % n. Now run the ordinary binary search on idx.
Read row by row, the grid is one sorted array of m · n numbers, and flat position idx is the cell matrix[idx / n][idx % n].
Problem
You are given a grid matrix with m rows and n columns. It has two promises:
- Every row is sorted from left to right.
- The first number of each row is bigger than the last number of the row above it.
Given a number target, return true if it appears anywhere in the grid, and false otherwise. Your solution must run in O(log(m · n)) time.
A 2D integer array matrix (m rows, n columns) with the two promises above, and an integer target.
true if target is in the matrix, otherwise false.
3 is in the first row, at column 1.
13 would have to sit between 11 and 16 in the middle row, but it is not there.
- • 1 ≤ m, n ≤ 100 (m rows, n columns)
- • −10^4 ≤ matrix[i][j], target ≤ 10^4
- • Each row is sorted in non-decreasing order.
- • The first number of each row is greater than the last number of the previous row.
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.
- 1.
If I read the grid row by row, left to right, what does the sequence of numbers look like?
- 2.
What does the second promise (each row starts bigger than the previous row ends) add on top of "each row is sorted"?
- 3.
Can I tell which row the target must be in just by looking at the first number of each row?
- 4.
If I number the cells 0, 1, 2, … in reading order, how do I get back the row and column of cell number k?
- 5.
Is O(log m + log n) really different from O(log(m · n))?
Brute force approach
Better approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | Scan all m · n cells and compare each one with target | O(m · n) | O(1) |
| Better | Binary search the rows by their first number, then binary search inside that row | O(log m + log n) | O(1) |
| Optimal | Treat the grid as one sorted array of m · n cells; map idx → (idx / n, idx % n) | O(log(m · n)) | O(1) |
Why does this belong to this pattern?
- “each row sorted”Sorted data → binary search is possible.
- “first of each row > last of previous row”The rows continue each other → the whole grid is ONE sorted array.
- “O(log(m · n))”One binary search over all m · n cells.
This is the anchor of the 2D and partition sub-pattern: it is the classic binary search in disguise. The only new skill is turning a flat index into (row, col). The next question, Search a 2D Matrix II, looks almost the same but drops the "rows continue each other" promise — and then flattening breaks.
Don't make this mistake
Each row holds n cells (the number of columns), so that is what you divide by. With a square grid both work, which hides the bug. Try the 3×4 example: flat index 5 is the value 11 at (1, 1). 5 / 4 = 1, 5 % 4 = 1 ✓. Using m = 3 gives (1, 2) = 16 ✗.
Pattern-confusion trap. In LC 240 each row and column is sorted, but a row does not start after the previous row ends. Example: [[1,4],[2,5]] read row by row is 1, 4, 2, 5 — not sorted. Binary search on that line gives wrong answers. Flattening only works when the second promise holds.
In the two-search approach, if target equals the first number of a row, < skips that row and you search the row above it, which can't contain target. Using <= keeps the row that starts with target.
With hi = mid − 1 the range lo == hi still holds one unchecked cell, so the loop must be lo <= hi. With lo < hi you never check that last cell; on a 1×1 matrix you'd return false without looking.
Want to implement this?
Write it yourself on LeetCode, then come back and compare your code with the solutions above.
Open coding workspaceHow this concept connects to System Design & C++ Systems
Top engineering interviews test whether you understand how algorithms like Binary Search translate into production architectures and low-level memory mechanics.