LeetCode #4 Hard

Median of Two Sorted Arrays

Return the median of two sorted arrays in O(log(min(n,m))).

binary-searcharraydivide-and-conquer
Open on LeetCode ↗
02

Intuition

The median splits the union into equal halves. So find a cut of A and a cut of B whose left parts together hold half the elements, with everything left of the cuts ≤ everything right. Binary search where to cut A — B's cut is then forced.

How to spot this pattern

When a problem demands better than O(n) on sorted input, you're binary searching something — and it isn't always the answer directly. Here you search over the partition point: how many elements of the smaller array fall on the left side. The median only needs the four values straddling that cut, never the merged array itself. Binary-searching a decision rather than a value is the move that also cracks split-array-largest-sum and koko-eating-bananas.

03

Approach

1

Cut both arrays

Cut A at i and B at j with i + j = (n+m+1)//2. Left halves combined = half the union (the +1 favours the left for odd totals).

2

Valid cut condition

Need A[i−1] ≤ B[j] and B[j−1] ≤ A[i] (±∞ sentinels at the edges). If A[i−1] > B[j], the cut in A is too far right — move left.

3

Read off the median

Odd total: max of the left halves. Even: average of max(left) and min(right). Search only the shorter array for O(log min(n,m)).

04

Solution & live demo

1class Solution:
2 def findMedianSortedArrays(self, a, b):
3 if len(a) > len(b): a, b = b, a
4 n, m = len(a), len(b)
5 half = (n + m + 1) // 2
6 lo, hi = 0, n
7 INF = float("inf")
8 while True:
9 i = (lo + hi) // 2
10 j = half - i
11 a_left = a[i-1] if i > 0 else -INF
12 a_right = a[i] if i < n else INF
13 b_left = b[j-1] if j > 0 else -INF
14 b_right = b[j] if j < m else INF
15 if a_left <= b_right and b_left <= a_right:
16 if (n + m) % 2: return max(a_left, b_left)
17 return (max(a_left, b_left) + min(a_right, b_right)) / 2
18 if a_left > b_right: hi = i - 1
19 else: lo = i + 1
05

Common pitfalls

Binary searching the larger array

✗ Wrong
lo, hi = 0, len(b)
✓ Right
if len(a) > len(b): a, b = b, a
lo, hi = 0, len(a)

j = half - i can then fall outside the other array's bounds, producing negative or oversized indices. Searching the shorter side keeps j legal for every i and pins the complexity to O(log min(m, n)).

Guarding the edges with real array values

✗ Wrong
a_left = a[i-1] if i > 0 else a[0]
✓ Right
a_left = a[i-1] if i > 0 else -INF

An empty left partition must never lose a comparison, and an empty right partition must never win one — that's precisely what the infinities encode. Substituting a real element makes the cut appear invalid and the search never converges.

Integer division on the final average

✗ Wrong
return (max(a_left, b_left) + min(a_right, b_right)) // 2
✓ Right
return (max(a_left, b_left) + min(a_right, b_right)) / 2

The median of an even-length set is genuinely fractional — [1, 2, 3, 4] gives 2.5. Floor division truncates it to 2.

06

Edge cases

One array empty

Cut takes 0 from it; sentinels handle every comparison — median of the other array.

All of A before all of B

Search pushes i to n; sentinel +∞ on A's right keeps checks valid.

07

Complexity

Time
O(log min(n,m))
Space
O(1)
Partition search on the shorter array.