matrix corner = flat index
flat index = row · cols + col
public boolean searchMatrix(int[][] matrix, int target) { int rows = matrix.length; int cols = matrix[0].length; int l = 0; int r = rows * cols - 1; while (l <= r) { int mid = l + (r - l) / 2; int row = mid / cols; int col = mid % cols; if (matrix[row][col] > target) { r = mid - 1; } else if (matrix[row][col] < target) { l = mid + 1; } else { return true; } } return false;}
- l
- —
- r
- —
- mid
- —
- (row, col)
- —
- matrix[row][col]
- —
- r − l + 1
- —
Why it works
- Brute force checks every cell: O(m·n). But each row is sorted and starts above the previous row's end, so the matrix read row by row is one sorted list of m·n values.
- Search that list without building it. Flat index
ilives at rowi / cols, columni % cols:i / colsfull rows come before it (integer division), andi % colsis how far into its row it sits. - Same template as 704:
l <= r,mid ± 1. O(log(m·n)) = O(log m + log n) time, O(1) space. - Pitfall: divide by
cols, the row length, notrows. On a square matrix both work, so the bug hides until the matrix is not square. - Alternative, two binary searches: first over the rows (is
targetbetweenrow[0]androw[cols - 1]?) to find the only row that could hold it, then a normal binary search inside that row. Same O(log m + log n), more code and more boundaries to get wrong. - Follow-up, 240 Search a 2D Matrix II: rows and columns sorted separately, with no global order, so the flat trick fails. Start at the top-right corner and step left or down: O(m + n).