Search a 2D Matrix

medium

You are given an m x n integer matrix matrix with two special properties:

  • Every row is sorted in non-decreasing order.
  • The first value of each row is strictly greater than the last value of the row above it.

Read those two properties together: the rows chain into one another, so the whole grid behaves like a single sorted list that just happens to be printed across several lines.

Given an integer target, return true if target appears anywhere in matrix, and false otherwise.

Your solution must run in O(log(m * n)) time.

Hints

Read the two matrix properties together, not separately. If you laid every row end to end on one long line, what would that line look like?
The flattened matrix is a single fully sorted array of m·n values. You already know the fastest way to search a sorted array — the only question is how to do it without building the array.
Binary search flat indices 0 … m·n − 1 directly: index i corresponds to matrix[i / n][i % n]. Division finds the row, remainder finds the column.

Common doubts

No — that would cost O(m·n) time and space and defeat the purpose. The mapping i / n → row, i % n → column gives O(1) access to any virtual position, so the matrix already behaves like a flat sorted array.
Within a row, yes — rows are non-decreasing. Across rows, no — each row starts strictly above the previous row's last value. Either way, a membership search doesn't care: binary search handles duplicates fine when you only need true/false.
That is O(m log n) — fine for small inputs but not the required O(log(m·n)). If you want a two-step search, binary search the rows first to find the single candidate row (the last row whose first element is <= target), then binary search inside it: O(log m + log n), which equals O(log(m·n)).
Always n, the number of columns — a flat index advances one column at a time, so every n steps completes one row. Using m happens to work on square matrices, which is exactly why the bug slips through casual testing.

Interview follow-ups

That is the harder variant (Search a 2D Matrix II). The flattened array is no longer sorted, so one binary search breaks. The staircase walk from the top-right corner still works, giving O(m + n).
Yes — binary search the first column (or the rows' first elements) to locate the only row that could contain the target, then binary search within that row. O(log m + log n), which is the same as O(log(m·n)); it's a perfectly acceptable answer if you articulate why the complexities are equal.
Return the pair (mid / n, mid % n) at the moment of the match, and a sentinel like (-1, -1) when the search range empties. The algorithm is unchanged.

Fun facts

  • The mapping i / n and i % n is exactly how computers lay out 2-D arrays in memory — row-major order. The virtual-flattening trick is just binary searching the matrix the way the hardware already sees it.
  • The staircase walk from a corner works on any grid whose rows and columns are independently sorted — it reappears in Search a 2D Matrix II and in several matrix counting problems, always with the same delete-a-row-or-column argument.

Asked at

AmazonMicrosoftGoogleBloombergApple
Frequently Sometimes Occasionally
Example 1
Input: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
Output: true
`3` sits in the first row, so the answer is `true`.
Example 2
Input: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
Output: false
`13` falls between `11` and `16` but is not present, so the answer is `false`.
Constraints

- m == matrix.length - n == matrix[i].length - 1 <= m, n <= 100 - -10^4 <= matrix[i][j], target <= 10^4

Solve this problem →