Median of Two Sorted Arrays

Table of contents
  1. Problem
  2. Explanation
  3. Solution

Problem

Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays.

Input: nums1 = [1,3], nums2 = [2]
Output: 2.00000
Explanation: merged array = [1,2,3] and median is 2.
Input: nums1 = [1,2], nums2 = [3,4]
Output: 2.50000
Explanation: merged array = [1,2,3,4] and median is (2 + 3) / 2 = 2.5.

Explanation

Let A and B be the two sorted arrays of size m and n respectively.

Let’s assume that mn.

Let x be the median of the two sorted arrays.

This x will divide each array into two parts:

AleftArightBleftBright

where Aleft and Bleft consist of respective elements x, and Aright and Bright consist of respective elements >x.

For x to be the median of the two sorted arrays, the following conditions must be satisfied:

  1. max(Aleft)min(Bright) and max(Bleft)min(Aright)
  2. If m+n is odd, then |Aleft|+|Bleft|=|Aright|+|Bright|+1.

    If m+n is even, then |Aleft|+|Bleft|=|Aright|+|Bright|

Let i be the number of elements in Aleft, and j be the number of elements in Bleft.

The first condition can be rewritten as:

ai1bjbj1ai

The notation follows the coding convention of 0-based indexing.

The second condition can be rewritten as:

|Aleft|+|Bleft|=|Aright|+|Bright|+1i+j=(mi)+(nj)+12j=m+n+12ij=m+n+12i

Later in code, the integer division truncating (m + n + 1) / 2 takes care of both odd and even cases.

We see that j is predetermined by i, so our problem boils down to finding the right i that satisfies the first condition.

Once we find the right i and j, we can compute the median x as follows:

x={max(ai1,bj1)if m+n is oddavg(max(ai1,bj1),min(ai,bj))if m+n is even
  • Why max(ai1,bj1) for odd m+n?

    Because we know the left side has one more element which is the median.

  • Why avg(max(ai1,bj1),min(ai,bj)) for even m+n?

    Because we want the average of the two middle elements.

Now we do a binary search on i in the range [0,m], to find the right i that satisfies the conditions.


Solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public double findMedianSortedArrays(int[] A, int[] B) {
  int m = A.length;
  int n = B.length;

  // Because we want to do a binary search on the smaller array
  if (m > n) return findMedianSortedArrays(B, A);

  // Setting candidate range for i
  int iMin = 0;
  int iMax = m;
  int lenCondition = (m + n + 1) / 2;

  while (iMin <= iMax) {
    int i = (iMin + iMax) / 2;
    int j = lenCondition - i;

    int maxALeft = (i < 1) ? Integer.MIN_VALUE : A[i - 1];
    int maxBLeft = (j < 1) ? Integer.MIN_VALUE : B[j - 1];
    int minARight = (i >= m) ? Integer.MAX_VALUE : A[i];
    int minBRight = (j >= n) ? Integer.MAX_VALUE : B[j];

    if (maxALeft <= minBRight && maxBLeft <= minARight) {
      if ((m + n) % 2 > 0) {  // When m + n is odd,
        return Math.max(maxALeft, maxBLeft);  // Median is at the left
      } else { // When m + n is even,
        // Median is the average of the two middle elements
        return (Math.max(maxALeft, maxBLeft) + Math.min(minARight, minBRight)) / 2.0;
      }
    } else if (maxALeft > minBRight) {  // We overshot our partition for A
      iMax = i - 1;
    } else {  // We undershot our partition for A
      iMin = i + 1;
    }
  }
  return 0.0;
}

Everything is explained in the Explanation section, except for the lines 17-20.

  • maxALeft: ai1
  • maxBLeft: bj1
  • minARight: ai
  • minBRight: bj

We must note that a partition of A and B by x may be empty.

Take A=[1,2] and B=[3,4], where the median 2.5 is not in the middle of the two arrays.

Aleft=[1,2]Aright=[]Bleft=[]Bright=[3,4]

We want ai1bj and bj1ai, but we can’t compare bj1 and ai because Bleft and Aright are empty.

That is why we need to turn them into

Aleft=[1,2]Aright=[]Bleft=[]Bright=[3,4]

By setting ai1,bj1= and ai,bj=, when indices are out of bound.

The complexity is O(log(min(m,n))).