Search a 2D Matrix
Table of Contents + β
This question hands you a grid instead of a flat list. It looks new. But the interviewer is checking one thing. Can you see that a sorted grid is really just a sorted list folded into rows? Once you see that, binary search works just like before.
π― The Problem
You search a sorted grid for a target number. The rules:
- A grid is a table of rows and columns, also called a matrix.
- Each row goes left to right from small to big.
- The first number of every row is bigger than the last number of the row above it.
- You get one target number.
- Return
trueif the target is in the grid, andfalseif it is not.
Let us say the grid is [[1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 60]] and the target is 16. The number 16 sits in the second row. So the answer is true.
Input: matrix = [[1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 60]], target = 16Output: true
Explanation: 16 is in the second row of the gridBecause of those two rules, if you read the grid row by row, the numbers come out in perfect sorted order. That is the secret.
Here is the grid. Read it left to right, top to bottom, and the values only go up.
π’ Approach 1: Check Every Cell (Brute Force)
Visit each cell and compare it with the target.
The idea:
- Walk through each row.
- Inside each row, walk through each number.
- Return
trueon a match. Returnfalseif the whole grid has none.
How it works:
- This is a linear scan over the grid.
- A linear scan visits every cell one after another.
- It works on any grid, even an unsorted one.
Why it is weak:
- Our grid is sorted, but this idea ignores that.
- With
mrows andncolumns, you might check allmtimesncells. - Time is O(m times n). Slow on a big grid.
Here is the brute-force code for that idea:
def search_matrix(matrix, target): for row in matrix: for value in row: if value == target: return True return Falseβ‘ Approach 2: Treat the Grid as One Sorted List (Best)
Read the grid as one long sorted list and binary search it.
The idea:
- The rows join up in order, so the whole grid behaves like one long sorted list.
- Run a single binary search across all the cells, as if laid out in a straight line.
How it works:
- There are
mtimesncells. Give each a flat number from0tomtimesnminus1. - Keep
loat0andhiat the last cell number. Pick the middlemid. - Turn
midinto a real cell: the row ismiddivided bynwith whole-number division, the column is the remaindermidmodn. - Read the value at that row and column.
- If it equals the target, return
true. - If it is smaller, move
lotomid + 1. If bigger, movehitomid - 1. - Stop when the window is empty and return
false.
Why it is fast:
- Each step halves the cells.
- Time is O(log of m times n).
- Only a few variables, so space is O(1).
Here is a dry run searching for 16 in a grid with 3 rows and 4 columns, so 12 cells. Watch the flat lo, mid and hi narrow.
Steps to Solve
- Read the number of rows
mand columnsn. - Set
loto0andhitomtimesnminus1. - While
lois less than or equal tohi, keep searching. - Find the middle cell number
midaslo + (hi - lo) / 2. - Turn
midinto a row withmid / nand a column withmid % n, then read the value. - If the value equals the target, return
true. - If the value is smaller, move
lotomid + 1. If bigger, movehitomid - 1. - If the loop ends with no match, return
false.
This Python version uses // for the row and % for the column to read each middle cell.
def search_matrix(matrix, target): m = len(matrix) n = len(matrix[0]) lo, hi = 0, m * n - 1 while lo <= hi: mid = lo + (hi - lo) // 2 # flat middle cell value = matrix[mid // n][mid % n] # row, column if value == target: return True # found it elif value < target: lo = mid + 1 # go right else: hi = mid - 1 # go left return False # not found
matrix = [[1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 60]]target = 16print(search_matrix(matrix, target))The output of the above code will be:
TrueLet us walk through the Python version line by line, so the index trick makes sense.
The lines m = len(matrix) and n = len(matrix[0]) read the shape of the grid. m is the number of rows. n is the number of columns. We need n to convert a flat number back into a row and column.
The line lo, hi = 0, m * n - 1 sets the edges over the imaginary flat list. There are m times n cells. So the last cell number is m * n - 1.
The line while lo <= hi: keeps searching while the window holds at least one cell.
The line mid = lo + (hi - lo) // 2 picks the middle flat cell number. Same overflow-safe form as plain binary search.
The line value = matrix[mid // n][mid % n] is the heart of this problem. mid // n is the row, because every n cells fill one full row. mid % n is the column, because the remainder tells you how far into the row you are. With both, we read the real value at that cell.
The line if value == target: returns True the moment we land on the target.
The line elif value < target: means the middle value is too small, so the target is later in the flat list. We set lo = mid + 1.
The else branch means the middle value is too big, so we set hi = mid - 1.
If the loop ends with nothing found, return False says the target is not in the grid.
β±οΈ Time and Space Complexity
The linear scan can touch every cell, so it is O(m times n). The binary search treats the grid as one sorted list and halves it each step, so it finishes in about log of m times n steps. Both use only a few variables, so the space is O(1).
| Approach | Time Complexity | Space Complexity |
|---|---|---|
| Linear scan over every cell | O(m times n) | O(1) |
| Binary search on the flat list | O(log of m times n) | O(1) |
Tip
The whole trick is row = mid / n and col = mid % n. Memorize that one line. It turns any sorted grid into a flat list you can binary search.
π§© Key Takeaways
- β A sorted grid with joined-up rows behaves like one long sorted list.
- β
Give each cell a flat number from
0tomtimesnminus1. - β
Turn a flat number into a row with
mid / nand a column withmid % n. - β After that conversion, it is plain binary search on the cell values.
- β The time is O(log of m times n), much faster than scanning every cell.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
Why can we run a single binary search over the whole grid?
Why: Each row is sorted and the next row starts higher, so reading row by row gives one sorted sequence.
- 2
How do you turn a flat cell number mid into a row?
Why: Every n cells fill one full row, so mid divided by n gives the row index.
- 3
How do you get the column from a flat cell number mid?
Why: The remainder mid % n tells you how far into the row the cell sits, which is the column.
- 4
What is the time complexity of the binary search approach?
Why: We binary search over m times n cells, halving each step, which is O(log of m times n).