← DSA
MEDIUM

Search a 2D Matrix

PracticeNeetCode ↗LeetCode ↗

Given an m×n matrix where each row is sorted left to right, and the first number of each row is larger than the last number of the previous row, return whether target exists anywhere in the matrix.

Example

Input matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
Output true

Key Pointers

Step-by-Step Analysis

  1. Let m, n be the matrix's dimensions; set left = 0, right = m*n - 1.
  2. While left has not passed right: compute mid, then convert it to row, col via divmod(mid, n).
  3. Compare matrix[row][col] to the target; if equal, return true.
  4. If the matrix value is smaller than the target, search the upper half of the flat range; otherwise search the lower half.
  5. If the loop ends without a match, return false.

Complexity

Time: O(log(m·n)) — Space: O(1)

Code

def searchMatrix(matrix: list[list[int]], target: int) -> bool:
    m, n = len(matrix), len(matrix[0])
    left, right = 0, m * n - 1

    while left <= right:
        mid = left + (right - left) // 2
        row, col = divmod(mid, n)
        val = matrix[row][col]
        if val == target:
            return True
        elif val < target:
            left = mid + 1
        else:
            right = mid - 1

    return False

Code Explanation

How the solution above works, piece by piece.

  1. Treat the m × n matrix as a single sorted array of length m * n: positions 0 to m*n − 1.
  2. Run ordinary binary search on those positions.
  3. row, col = divmod(mid, n): position ÷ row length gives the row, the remainder gives the column.
  4. Compare and move left or right exactly as in plain binary search.
  5. O(log(m·n)) time and O(1) space: no copying into a real list.

Visual Walkthrough

Running it on the 3 × 4 example with target = 3:

Matrix treated as one sorted list of 12, with binary search probes1031527310411516620723830934106011probe 1: mid = 5 → row 1, col 1 → 11probe 2: mid = 2 → row 0, col 2 → 5probe 3: mid = 0 → row 0, col 0 → 1probe 4: mid = 1 → row 0, col 1 → 3(small numbers = index in the flattened list)
Rows are sorted and each row starts after the previous one ends, so reading row by row gives one sorted list of 12. divmod(mid, n) turns a list position back into (row, column) without building the list.
probedfound

Video Explanation

NeetCode — Search a 2D Matrix, LeetCode 74