Skip to content

Saddleback Search

Search a matrix sorted by rows and columns using a monotone path from a corner.

Saddleback search finds a target in a matrix where each row and each column is sorted in nondecreasing order. It walks through the matrix along a monotone path, eliminating one row or one column at each step.

Problem

Given a matrix AA of size n×mn \times m such that:

A[i][j]A[i][j+1](rows sorted) A[i][j] \le A[i][j+1] \quad \text{(rows sorted)} A[i][j]A[i+1][j](columns sorted) A[i][j] \le A[i+1][j] \quad \text{(columns sorted)}

find a position (i,j)(i, j) such that:

A[i][j]=x A[i][j] = x

If no such position exists, return (1,1)(-1, -1).

Key Idea

Start from the top-right corner:

  • At (0,m1)(0, m-1)

At each step:

  • If current value equals xx, return it
  • If current value is greater than xx, move left
  • If current value is less than xx, move down

Each move discards one row or one column.

Algorithm

saddleback_search(A, x):
    n = number of rows
    m = number of columns

    i = 0
    j = m - 1

    while i < n and j >= 0:
        if A[i][j] == x:
            return (i, j)
        else if A[i][j] > x:
            j = j - 1
        else:
            i = i + 1

    return (-1, -1)

Example

Let

A=[14711 25812 36916 10131417] A = \begin{bmatrix} 1 & 4 & 7 & 11 \ 2 & 5 & 8 & 12 \ 3 & 6 & 9 & 16 \ 10 & 13 & 14 & 17 \end{bmatrix}

and

x=9 x = 9

Path:

steppositionvalueaction
1(0, 3)11move left
2(0, 2)7move down
3(1, 2)8move down
4(2, 2)9found

Return (2,2)(2, 2).

Correctness

At each step, the algorithm maintains a candidate region where the target may lie.

From the top-right corner:

  • All elements below are larger
  • All elements to the left are smaller

If A[i][j]>xA[i][j] > x, then every element below in column jj is greater than or equal to A[i][j]A[i][j], so none can equal xx. The column can be discarded.

If A[i][j]<xA[i][j] < x, then every element to the left in row ii is less than or equal to A[i][j]A[i][j], so none can equal xx. The row can be discarded.

Each step reduces the search space while preserving all possible positions of xx.

Complexity

dimensioncost
rowsnn
columnsmm
totalO(n+m)O(n + m)

Space:

O(1) O(1)

Comparison

methodrequirementtime
full scannoneO(nm)O(nm)
binary search per rowrows sortedO(nlogm)O(n \log m)
saddleback searchrows and columns sortedO(n+m)O(n + m)

Variants

start pointdirection
top-rightmove left or down
bottom-leftmove up or right

Both give the same complexity.

When to Use

  • Matrix sorted by rows and columns
  • Efficient elimination of rows or columns
  • Large matrices where n+mnmn + m \ll nm

Notes

  • Does not require global ordering across rows
  • Works with duplicates
  • Deterministic path with no backtracking

Implementation

def saddleback_search(a, x):
    if not a or not a[0]:
        return -1, -1

    n, m = len(a), len(a[0])
    i, j = 0, m - 1

    while i < n and j >= 0:
        if a[i][j] == x:
            return i, j
        elif a[i][j] > x:
            j -= 1
        else:
            i += 1

    return -1, -1
func SaddlebackSearch(a [][]int, x int) (int, int) {
    if len(a) == 0 || len(a[0]) == 0 {
        return -1, -1
    }

    n, m := len(a), len(a[0])
    i, j := 0, m-1

    for i < n && j >= 0 {
        if a[i][j] == x {
            return i, j
        } else if a[i][j] > x {
            j--
        } else {
            i++
        }
    }

    return -1, -1
}