Median of Two Sorted Arrays
Binary search on the partition of the smaller array — find a split with equal-sized halves and left ≤ right on both sides.
6 min read
binary-search divide-and-conquer
Problem#
Find the median of two sorted arrays in O(log(m+n)).
Examples#
[1,3], [2]→2.0.[1,2], [3,4]→2.5.
Constraints#
0 <= m + n <= 2000, total ≥ 1.
Approach#
Binary-search the partition point in the shorter array. For each candidate i (split of A), compute j = half - i (split of B). Check A[i-1] <= B[j] and B[j-1] <= A[i]. Median is then derived from the four boundary values.
Solution#
class Solution {public: double findMedianSortedArrays(vector<int>& A, vector<int>& B) { if (A.size() > B.size()) return findMedianSortedArrays(B, A); int m = A.size(), n = B.size(); int total = m + n, half = (total + 1) / 2; int lo = 0, hi = m; while (lo <= hi) { int i = (lo + hi) / 2; int j = half - i; int Aleft = (i == 0) ? INT_MIN : A[i - 1]; int Aright = (i == m) ? INT_MAX : A[i]; int Bleft = (j == 0) ? INT_MIN : B[j - 1]; int Bright = (j == n) ? INT_MAX : B[j]; if (Aleft <= Bright && Bleft <= Aright) { if (total % 2) return max(Aleft, Bleft); return (max(Aleft, Bleft) + min(Aright, Bright)) / 2.0; } else if (Aleft > Bright) hi = i - 1; else lo = i + 1; } return 0.0; }};import "math"
func findMedianSortedArrays(A []int, B []int) float64 { if len(A) > len(B) { A, B = B, A } m, n := len(A), len(B) total := m + n half := (total + 1) / 2 lo, hi := 0, m for lo <= hi { i := (lo + hi) / 2 j := half - i Aleft := math.MinInt32 if i > 0 { Aleft = A[i-1] } Aright := math.MaxInt32 if i < m { Aright = A[i] } Bleft := math.MinInt32 if j > 0 { Bleft = B[j-1] } Bright := math.MaxInt32 if j < n { Bright = B[j] } if Aleft <= Bright && Bleft <= Aright { maxLeft := Aleft if Bleft > maxLeft { maxLeft = Bleft } if total%2 == 1 { return float64(maxLeft) } minRight := Aright if Bright < minRight { minRight = Bright } return float64(maxLeft+minRight) / 2.0 } else if Aleft > Bright { hi = i - 1 } else { lo = i + 1 } } return 0.0}from typing import List
class Solution: def findMedianSortedArrays(self, A: List[int], B: List[int]) -> float: if len(A) > len(B): A, B = B, A m, n = len(A), len(B) total = m + n half = (total + 1) // 2 lo, hi = 0, m while lo <= hi: i = (lo + hi) // 2 j = half - i Aleft = A[i - 1] if i > 0 else float('-inf') Aright = A[i] if i < m else float('inf') Bleft = B[j - 1] if j > 0 else float('-inf') Bright = B[j] if j < n else float('inf') if Aleft <= Bright and Bleft <= Aright: if total % 2: return float(max(Aleft, Bleft)) return (max(Aleft, Bleft) + min(Aright, Bright)) / 2.0 elif Aleft > Bright: hi = i - 1 else: lo = i + 1 return 0.0function findMedianSortedArrays(A, B) { if (A.length > B.length) [A, B] = [B, A]; const m = A.length, n = B.length; const total = m + n; const half = (total + 1) >> 1; let lo = 0, hi = m; while (lo <= hi) { const i = (lo + hi) >> 1; const j = half - i; const Aleft = i === 0 ? -Infinity : A[i - 1]; const Aright = i === m ? Infinity : A[i]; const Bleft = j === 0 ? -Infinity : B[j - 1]; const Bright = j === n ? Infinity : B[j]; if (Aleft <= Bright && Bleft <= Aright) { if (total % 2) return Math.max(Aleft, Bleft); return (Math.max(Aleft, Bleft) + Math.min(Aright, Bright)) / 2.0; } else if (Aleft > Bright) hi = i - 1; else lo = i + 1; } return 0.0;}class Solution { public double findMedianSortedArrays(int[] A, int[] B) { if (A.length > B.length) return findMedianSortedArrays(B, A); int m = A.length, n = B.length; int total = m + n, half = (total + 1) / 2; int lo = 0, hi = m; while (lo <= hi) { int i = (lo + hi) / 2; int j = half - i; int Aleft = (i == 0) ? Integer.MIN_VALUE : A[i - 1]; int Aright = (i == m) ? Integer.MAX_VALUE : A[i]; int Bleft = (j == 0) ? Integer.MIN_VALUE : B[j - 1]; int Bright = (j == n) ? Integer.MAX_VALUE : B[j]; if (Aleft <= Bright && Bleft <= Aright) { if (total % 2 == 1) return Math.max(Aleft, Bleft); return (Math.max(Aleft, Bleft) + Math.min(Aright, Bright)) / 2.0; } else if (Aleft > Bright) hi = i - 1; else lo = i + 1; } return 0.0; }}function findMedianSortedArrays(A: number[], B: number[]): number { if (A.length > B.length) [A, B] = [B, A]; const m = A.length, n = B.length; const total = m + n; const half = (total + 1) >> 1; let lo = 0, hi = m; while (lo <= hi) { const i = (lo + hi) >> 1; const j = half - i; const Aleft = i === 0 ? -Infinity : A[i - 1]; const Aright = i === m ? Infinity : A[i]; const Bleft = j === 0 ? -Infinity : B[j - 1]; const Bright = j === n ? Infinity : B[j]; if (Aleft <= Bright && Bleft <= Aright) { if (total % 2) return Math.max(Aleft, Bleft); return (Math.max(Aleft, Bleft) + Math.min(Aright, Bright)) / 2.0; } else if (Aleft > Bright) hi = i - 1; else lo = i + 1; } return 0.0;}Editorial#
Searching on the smaller array bounds the work to O(log min(m, n)). The four boundary checks with INT_MIN/INT_MAX sentinels handle empty-half edges cleanly. Half-size is (total + 1) / 2 so the odd-length case picks the median on the left side.
Complexity#
- Time:
O(log min(m, n)). - Space:
O(1).
Concept revision#
Related#