150NeetCode 150

34.Median of Two Sorted Arrays

HardBinary Search ยท 7/7
LeetCode #4Video

Problem

Given two sorted arrays nums1 (size m) and nums2 (size n), return the median of the combined multiset of their elements.

The overall run time complexity should be O(log(m + n)). The median is the middle value of the merged sorted order; if the total count is even, it is the average of the two middle values.

Examples

Input:  nums1 = [1, 3], nums2 = [2]
Output: 2.00000
Explanation: merged = [1, 2, 3]; the middle element is 2.
Input:  nums1 = [1, 2], nums2 = [3, 4]
Output: 2.50000
Explanation: merged = [1, 2, 3, 4]; median = (2 + 3) / 2 = 2.5.
Input:  nums1 = [], nums2 = [5]
Output: 5.00000

Constraints

  • nums1.length == m, nums2.length == n
  • 0 <= m <= 1000, 0 <= n <= 1000
  • 1 <= m + n <= 2000
  • -10^6 <= nums1[i], nums2[i] <= 10^6

๐Ÿ’ก Key Insight

The median splits the merged array into a left half and a right half of equal size (left gets the extra element when the total is odd). If we take i elements from nums1 and j = half - i from nums2 for the left half, the split is correct exactly when nums1[i-1] <= nums2[j] and nums2[j-1] <= nums1[i]. Choosing i determines j, and the conditions are monotonic in i, so we can binary-search i over the shorter array โ€” O(log(min(m, n))) without merging anything.

Brute Force (Merge Into New Array)

TimeO(m + n)SpaceO(m + n)

Intuition

Do exactly what the definition says: merge both sorted arrays into one sorted array (the merge step of merge sort), then read off the middle element(s).

Algorithm

  1. Create merged of size m + n; merge with two pointers, always copying the smaller head.
  2. Copy any leftovers.
  3. If total is odd return merged[total / 2]; else return the average of merged[total/2 - 1] and merged[total/2].

Visualization

nums1 = [1, 2], nums2 = [3, 4]
merged = [1, 2, 3, 4]
             ^  ^
     middles 2 and 3 โ†’ (2 + 3) / 2 = 2.5

Code

java
class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int m = nums1.length, n = nums2.length;
        int[] merged = new int[m + n];
        int i = 0, j = 0, k = 0;
        while (i < m && j < n) {
            merged[k++] = (nums1[i] <= nums2[j]) ? nums1[i++] : nums2[j++];
        }
        while (i < m) {
            merged[k++] = nums1[i++];
        }
        while (j < n) {
            merged[k++] = nums2[j++];
        }
        int total = m + n;
        if (total % 2 == 1) {
            return merged[total / 2];
        }
        return (merged[total / 2 - 1] + merged[total / 2]) / 2.0;
    }
}

Complexity

  • Time: O(m + n) โ€” every element is copied once.
  • Space: O(m + n) โ€” the merged array.

Complexity Comparison

Approach Time Space
Merge Into New Array O(m + n) O(m + n)
Two Pointers O(m + n) O(1)
Binary Search on Partition O(log(min(m, n))) O(1)

Common Pitfalls

  • Binary-searching the longer array โ€” then j = half - i can become negative or exceed n, causing index errors.
  • Forgetting the sentinels: when i == 0, i == m, j == 0 or j == n one side is empty and must act as -โˆž / +โˆž.
  • Integer division for the even case: (a + b) / 2 truncates; divide by 2.0 (and cast to double before adding to avoid overflow).
  • Using half = (m + n) / 2 with "median = max(left)" for odd totals โ€” the extra element then lands on the right side and you would need min(R1, R2) instead. Pick one convention and stay consistent.
  • Handling an empty array: the optimal code covers m = 0 naturally (i is always 0).