Median Of Two Sorted Arrays
Worked solution, explanation, and GitHub source for this problem.
04. Median of Two Sorted Arrays
LeetCode: Problem #4
Difficulty: Hard
Topics: Array Binary Search Divide and Conquer
Problem Statement
Given two sorted arrays nums1 and nums2 of sizes m and n, return the
median of the two sorted arrays.
The overall runtime complexity must be O(log(m + n)).
Constraints:
0 <= m, n <= 10001 <= m + n <= 2000-10⁶ <= nums1[i], nums2[i] <= 10⁶
Example
Input: nums1 = [1, 3], nums2 = [2]
Output: 2.0
Explanation: Merged array is [1, 2, 3], median is 2.
Input: nums1 = [1, 2], nums2 = [3, 4]
Output: 2.5
Explanation: Merged array is [1, 2, 3, 4], median is (2 + 3) / 2 = 2.5
How to Think About This Problem
Step 1 — Understand what the median means in terms of partitions
The median splits a sorted sequence into two equal halves. In a merged array of
size m + n, the left half has (m + n) // 2 elements. The median is the
largest element of the left half (odd total) or the average of the largest in
the left half and smallest in the right half (even total).
We don't need to build the merged array. We just need to find the right split point across both arrays.
Step 2 — Identify the constraint that matters
The O(log(m + n)) requirement rules out merging the arrays. We need binary
search. The key insight: if we choose how many elements to take from nums1
(call it i), then we know exactly how many to take from nums2 (j = half - i).
Binary search on i.
Step 3 — Think about what a valid partition looks like
A partition is valid when:
maxLeft1 <= minRight2— left part of nums1 ≤ right part of nums2maxLeft2 <= minRight1— left part of nums2 ≤ right part of nums1
If both conditions hold, the combined left half contains the correct elements.
Step 4 — Build the intuition
Binary search on the shorter array. For each candidate partition of nums1,
compute the forced partition of nums2. Check the boundary conditions. Adjust
left/right pointers based on which side violates the condition.
Approaches
Approach 1 — Brute Force (Merge and Find)
Intuition: Merge both arrays, then find the median of the merged array.
Steps:
- Concatenate both arrays and sort
- If total length is odd, return the middle element
- If even, return the average of the two middle elements
Complexity:
- Time: O((m + n) log(m + n)) — sorting dominates
- Space: O(m + n) — stores the merged array
Code:
def findMedianSortedArrays_brute(nums1, nums2):
merged = sorted(nums1 + nums2)
n = len(merged)
if n % 2 == 1:
return float(merged[n // 2])
return (merged[n // 2 - 1] + merged[n // 2]) / 2.0
Approach 2 — Optimal (Binary Search on Partition)
Intuition: Binary search on the smaller array to find the partition point
i such that nums1[:i] + nums2[:j] forms exactly the left half of the
merged array. Check the four boundary values to confirm a valid partition.
Steps:
- Ensure
nums1is the shorter array (swap if needed) - Binary search
iin range[0, m] - Compute
j = half - i - Compute the four boundary values:
maxLeft1,minRight1,maxLeft2,minRight2 - If partition is valid, compute and return the median
- If
maxLeft1 > minRight2, moveright = i - 1(i is too large) - Otherwise
left = i + 1(i is too small)
Illustration:
nums1 = [1, 3], nums2 = [2, 4], m=2, n=2, half=2
Try i=1, j=1:
maxLeft1 = nums1[0] = 1
minRight1 = nums1[1] = 3
maxLeft2 = nums2[0] = 2
minRight2 = nums2[1] = 4
maxLeft1(1) <= minRight2(4) ✓
maxLeft2(2) <= minRight1(3) ✓
→ valid partition!
Total even → median = (max(1,2) + min(3,4)) / 2 = (2 + 3) / 2 = 2.5 ✓
Complexity:
- Time: O(log(min(m, n))) — binary search on the shorter array
- Space: O(1) — only pointer variables
Code:
def findMedianSortedArrays(nums1, nums2):
if len(nums1) > len(nums2):
nums1, nums2 = nums2, nums1
m, n = len(nums1), len(nums2)
half = (m + n) // 2
left, right = 0, m
while left <= right:
i = (left + right) // 2
j = half - i
maxLeft1 = float('-inf') if i == 0 else nums1[i - 1]
minRight1 = float('inf') if i == m else nums1[i]
maxLeft2 = float('-inf') if j == 0 else nums2[j - 1]
minRight2 = float('inf') if j == n else nums2[j]
if maxLeft1 <= minRight2 and maxLeft2 <= minRight1:
if (m + n) % 2 == 1:
return float(min(minRight1, minRight2))
return (max(maxLeft1, maxLeft2) + min(minRight1, minRight2)) / 2.0
elif maxLeft1 > minRight2:
right = i - 1
else:
left = i + 1
Solution Breakdown — Step by Step
def findMedianSortedArrays(nums1, nums2):
if len(nums1) > len(nums2):
nums1, nums2 = nums2, nums1
m, n = len(nums1), len(nums2)
half = (m + n) // 2
left, right = 0, m
while left <= right:
i = (left + right) // 2
j = half - i
maxLeft1 = float('-inf') if i == 0 else nums1[i - 1]
minRight1 = float('inf') if i == m else nums1[i]
maxLeft2 = float('-inf') if j == 0 else nums2[j - 1]
minRight2 = float('inf') if j == n else nums2[j]
if maxLeft1 <= minRight2 and maxLeft2 <= minRight1:
if (m + n) % 2 == 1:
return float(min(minRight1, minRight2))
return (max(maxLeft1, maxLeft2) + min(minRight1, minRight2)) / 2.0
elif maxLeft1 > minRight2:
right = i - 1
else:
left = i + 1
Line by line:
if len(nums1) > len(nums2): nums1, nums2 = nums2, nums1
- Always binary search on the shorter array — reduces search space and prevents
jfrom going out of bounds
half = (m + n) // 2
- The left half of the merged array always has exactly this many elements
i = (left + right) // 2
iis the number of elements we take fromnums1into the left half
j = half - i
- The remaining elements in the left half come from
nums2
maxLeft1 = float('-inf') if i == 0 else nums1[i - 1]
- Edge case: if we take zero elements from
nums1, treat the left boundary as -∞
minRight1 = float('inf') if i == m else nums1[i]
- Edge case: if we take all elements from
nums1, treat the right boundary as +∞
if maxLeft1 <= minRight2 and maxLeft2 <= minRight1:
- Both cross-conditions must hold — this is what makes the partition valid
return float(min(minRight1, minRight2))
- Odd total: median is the smallest element in the right half
return (max(maxLeft1, maxLeft2) + min(minRight1, minRight2)) / 2.0
- Even total: average of the largest in the left half and smallest in the right half
Quick Summary
| Approach | Time | Space |
|---|---|---|
| Brute Force (merge + sort) | O((m+n) log(m+n)) | O(m+n) |
| Optimal (binary search on partition) | O(log(min(m,n))) | O(1) |
Common Mistakes
1. Not swapping to ensure nums1 is shorter
# WRONG — j can become negative if nums1 is longer
i = (0 + len(nums1)) // 2
j = half - i # may be negative if m > n
Always swap so that m <= n. This guarantees j stays in [0, n].
2. Using wrong boundary sentinels
# WRONG — using 0 instead of -inf / inf breaks the comparison
maxLeft1 = 0 if i == 0 else nums1[i - 1]
Use float('-inf') and float('inf') — the boundary comparison must be safe
even when one side contributes no elements.
3. Adjusting the wrong pointer
# WRONG — when maxLeft1 > minRight2, i is too big, move right
left = i + 1 # should be: right = i - 1
If maxLeft1 > minRight2, nums1's partition is too far right — decrease i.
4. Off-by-one in left and right initialization
left, right = 0, m - 1 # WRONG — i == m must be reachable (take all of nums1)
Initialize right = m, not m - 1.
Pattern Recognition
How to Recognize
- Two sorted arrays, need a combined property in O(log n)
- Problem involves finding a specific rank/position across merged data
- Merging is too expensive — the sorted property must be exploited
How to Identify
- Can you express the answer as "pick
ielements from array 1 andjfrom array 2"? - Does binary searching on the partition point satisfy the O(log n) constraint?
How to Remember
Mental model: Don't merge — partition. Binary search for the right cut point across both arrays simultaneously.
Similar problems:
- Kth Smallest Element in a Sorted Matrix — same idea extended to 2D
- Find K-th Smallest Pair Distance — binary search on the answer value
- Split Array Largest Sum — binary search on the answer, not an index
Real World Use Cases
1. Distributed statistics aggregation
Data warehouses that process sorted event streams from multiple sources (e.g., two data centers sorted by timestamp) need to compute quantiles without merging petabytes. The partition-based approach computes the median in O(log n) per query.
2. Real-time sensor fusion
In autonomous vehicles, two LiDAR sensors produce sorted distance readings. Computing the median reading (to filter noise) in real time requires O(log n) rather than sorting the combined feed.
3. Merge-sort based distributed search
Search engines that maintain sorted inverted index shards use the same partition logic to find the globally-ranked kth document across shards without full merges.
Key Takeaways
- The median partitions the merged array into two equal halves — binary search for the right partition instead of building the array
- Always binary search on the shorter array to keep
jin bounds - Four boundary values (
maxLeft1,minRight1,maxLeft2,minRight2) define whether the partition is valid - Edge cases (
i == 0ori == m) require-∞/+∞sentinels - This is the hardest application of binary search in the Blind 75 — master the partition invariant
Where to Practice
| Platform | Problem | Difficulty |
|---|---|---|
| LeetCode #4 | Median of Two Sorted Arrays | Hard |
Part of the Blind 75 and NeetCode 150 interview prep lists.