LC 4 ยท Median of Two Sorted Arrays โ Solution & Explanation | DSA Guide
Two approaches to LeetCode Median of Two Sorted Arrays โ merge O(m+n) and optimal binary search on partition O(log min(m,n)). Java and Python solutions.
LeetCode ยท #4
Median of Two Sorted Arrays Solution
Given two sorted arrays nums1 and nums2, return the median of the combined sorted array in O(log(m+n)) time.
Given two sorted arrays nums1 (size m) and nums2 (size n), return the median of the two sorted arrays. The overall run time complexity must be O(log(m+n)).
โข nums1.length == m, nums2.length == nโข 0 โค m, n โค 1000โข 1 โค m + n โค 2000โข -10โถ โค nums1[i], nums2[i] โค 10โถ
02
Section Two ยท Approach 1
Merge & Find โ O(m + n)
Merge both arrays into one sorted array (like merge sort's merge step), then pick the middle element(s). Correct but O(m+n) time and space.
Problem: O(m+n) violates the O(log(m+n)) requirement. We don't need the full merged array โ we just need to find the correct partition point using binary search on the smaller array.
Java โ Merge
classSolution {
publicdoublefindMedianSortedArrays(int[] a, int[] b) {
int[] merged = newint[a.length + b.length];
int i = 0, j = 0, k = 0;
while (i < a.length && j < b.length)
merged[k++] = a[i] <= b[j] ? a[i++] : b[j++];
while (i < a.length) merged[k++] = a[i++];
while (j < b.length) merged[k++] = b[j++];
int n = merged.length;
return n % 2 == 1 ? merged[n/2] : (merged[n/2-1] + merged[n/2]) / 2.0;
}
}
Python โ Merge
classSolution:
deffindMedianSortedArrays(self, a: list[int], b: list[int]) -> float:
merged = sorted(a + b)
n = len(merged)
if n % 2: return merged[n // 2]
return (merged[n // 2 - 1] + merged[n // 2]) / 2
Metric
Value
Time
O(m + n)
Space
O(m + n)
03
Section Three ยท Approach 2
Binary Search on Partition โ O(log min(m, n))
The median divides the combined array into two equal halves. We binary search on the smaller array to find how many elements it contributes to the left half. The remaining come from the larger array. A valid partition satisfies: maxLeft1 โค minRight2 and maxLeft2 โค minRight1.
๐ก Mental model: Imagine cutting two decks of sorted cards so that when you combine the left portions, you have exactly half the total cards โ and every card on the left is โค every card on the right. You slide the cut point on the smaller deck; the cut on the larger deck adjusts automatically (it takes whatever is needed to make up half). Binary search finds the correct cut in O(log n) tries.
Algorithm
Step 1: Ensure nums1 is the smaller array (swap if needed).
Step 2: Binary search i on nums1: left = 0, right = m. Compute j = half - i where half = (m+n+1)/2.
Partition search โ split into equal left/right halves
05
Section Five ยท Implementation
Code โ Java & Python
Java โ Binary Search on Partition
classSolution {
publicdoublefindMedianSortedArrays(int[] nums1, int[] nums2) {
// Ensure nums1 is the smaller arrayif (nums1.length > nums2.length)
return findMedianSortedArrays(nums2, nums1);
int m = nums1.length, n = nums2.length;
int left = 0, right = m;
int half = (m + n + 1) / 2;
while (left <= right) {
int i = left + (right - left) / 2; // partition in nums1int j = half - i; // partition in nums2int maxLeft1 = (i == 0) ? Integer.MIN_VALUE : nums1[i - 1];
int minRight1 = (i == m) ? Integer.MAX_VALUE : nums1[i];
int maxLeft2 = (j == 0) ? Integer.MIN_VALUE : nums2[j - 1];
int minRight2 = (j == n) ? Integer.MAX_VALUE : nums2[j];
if (maxLeft1 <= minRight2 && maxLeft2 <= minRight1) {
// Valid partitionif ((m + n) % 2 == 1)
returnMath.max(maxLeft1, maxLeft2);
return (Math.max(maxLeft1, maxLeft2)
+ Math.min(minRight1, minRight2)) / 2.0;
} else if (maxLeft1 > minRight2) {
right = i - 1; // too far right in nums1
} else {
left = i + 1; // too far left in nums1
}
}
return0.0; // unreachable
}
}
Python โ Binary Search on Partition
classSolution:
deffindMedianSortedArrays(self, nums1: list[int], nums2: list[int]) -> float:
if len(nums1) > len(nums2):
nums1, nums2 = nums2, nums1
m, n = len(nums1), len(nums2)
left, right = 0, m
half = (m + n + 1) // 2while left <= right:
i = (left + right) // 2
j = half - i
max_l1 = float('-inf') if i == 0else nums1[i - 1]
min_r1 = float('inf') if i == m else nums1[i]
max_l2 = float('-inf') if j == 0else nums2[j - 1]
min_r2 = float('inf') if j == n else nums2[j]
if max_l1 <= min_r2 and max_l2 <= min_r1:
if (m + n) % 2:
return max(max_l1, max_l2)
return (max(max_l1, max_l2) + min(min_r1, min_r2)) / 2elif max_l1 > min_r2:
right = i - 1else:
left = i + 1
06
Section Six ยท Analysis
Complexity Analysis
Approach
Time
Space
Trade-off
Merge
O(m + n)
O(m + n)
Simple but linear
Two-pointer count
O(m + n)
O(1)
No extra array but still linear
Binary Partition โ optimal
O(log min(m,n))
O(1)
Search on the smaller array's partition
Why search the smaller array?:
Binary searching on the smaller array (m โค n) gives O(log m).
The partition in the larger array is determined automatically: j = half - i.
This guarantees j โฅ 0 because we ensured m โค n.
07
Section Seven ยท Edge Cases
Edge Cases & Pitfalls
Case
Input
Why It Matters
One empty
[], [1,2,3]
i always 0, j = half. Median from nums2 alone.
Disjoint
[1,2], [3,4]
All of nums1 on left, partition cleanly at boundary.
Interleaved
[1,3], [2,4]
Elements alternate โ partition must carefully balance.
Odd total
[1,3], [2]
Merged [1,2,3] โ median = max of left half = 2.
Equal elements
[1,1], [1,1]
All same โ partition anywhere works. Median = 1.0.
โ Common Mistake: Not swapping to ensure nums1 is smaller. If you binary search on the larger array, j = half - i can become negative (when i is too large), causing an index-out-of-bounds error. Always ensure m โค n before the search.