Skip to content

Equal Range Search

Find the range of indices containing all occurrences of a value in a sorted array.

Equal range search finds the contiguous range of indices where a value xx appears in a sorted array. It returns a pair of indices:

[l,r) [l, r)

such that all elements equal to xx lie within this interval.

This operation combines lower bound and upper bound.

Problem

Given a sorted array AA of length nn and a value xx, find indices ll and rr such that:

A[i]=xfor all i[l,r) A[i] = x \quad \text{for all } i \in [l, r)

If xx does not appear, return an empty range where l=rl = r.

Key Idea

Compute:

  • l=lower_bound(x)l = \text{lower\_bound}(x)
  • r=upper_bound(x)r = \text{upper\_bound}(x)

Then:

[l,r) [l, r)

contains all occurrences of xx.

Algorithm

equal_range(A, x):
    l = lower_bound(A, x)
    r = upper_bound(A, x)
    return (l, r)

Example

Let

A=[1,3,3,3,5,7] A = [1, 3, 3, 3, 5, 7]

and

x=3 x = 3

Then:

  • lower bound = 11
  • upper bound = 44

So the result is:

[1,4) [1, 4)

Interpretation

  • Elements in [l,r)[l, r) are equal to xx
  • Elements before ll are less than xx
  • Elements from rr onward are greater than xx

This forms a clean partition of the array.

Correctness

Lower bound ensures:

A[l]x A[l] \ge x

Upper bound ensures:

A[r]>x A[r] > x

Together:

  • all indices in [l,r)[l, r) satisfy A[i]=xA[i] = x
  • no index outside the range contains xx

Complexity

operationtime
lower boundO(logn)O(\log n)
upper boundO(logn)O(\log n)
totalO(logn)O(\log n)

Space:

O(1) O(1)

Use Cases

  • Count occurrences:
rl r - l
  • Range queries in sorted arrays
  • Deduplication boundaries
  • Frequency counting without scanning

Implementation

def equal_range(a, x):
    def lower_bound(a, x):
        l, r = 0, len(a)
        while l < r:
            m = l + (r - l) // 2
            if a[m] < x:
                l = m + 1
            else:
                r = m
        return l

    def upper_bound(a, x):
        l, r = 0, len(a)
        while l < r:
            m = l + (r - l) // 2
            if a[m] <= x:
                l = m + 1
            else:
                r = m
        return l

    l = lower_bound(a, x)
    r = upper_bound(a, x)
    return (l, r)
func EqualRange(a []int, x int) (int, int) {
    lower := func(a []int, x int) int {
        l, r := 0, len(a)
        for l < r {
            m := l + (r-l)/2
            if a[m] < x {
                l = m + 1
            } else {
                r = m
            }
        }
        return l
    }

    upper := func(a []int, x int) int {
        l, r := 0, len(a)
        for l < r {
            m := l + (r-l)/2
            if a[m] <= x {
                l = m + 1
            } else {
                r = m
            }
        }
        return l
    }

    l := lower(a, x)
    r := upper(a, x)
    return l, r
}