Median of two sorted arrays of different sizes


Given two sorted arrays, a[] and b[], the task is to find the median of these sorted arrays, in O(log n + log m) time complexity, when n is the number of elements in the first array, and m is the number of elements in the second array.

This is an extension of median of two sorted arrays of equal size problem. Here we handle arrays of unequal size also.

Example:

Input: ar1[] = {-5, 3, 6, 12, 15}
        ar2[] = {-12, -10, -6, -3, 4, 10}
Output : The median is 3.
Explanation : The merged array is :
        ar3[] = {-12, -10, -6, -5 , -3,
                 3, 4, 6, 10, 12, 15},
       So the median of the merged array is 3

Input: ar1[] = {2, 3, 5, 8}
        ar2[] = {10, 12, 14, 16, 18, 20}
Output : The median is 11.
Explanation : The merged array is :
        ar3[] = {2, 3, 5, 8, 10, 12, 14, 16, 18, 20}
        if the number of the elements are even, 
        so there are two middle elements,
        take the average between the two :
        (10 + 12) / 2 = 11.      

Method 1: This method uses a linear and simpler approach.

  • Approach: The given arrays are sorted, so merge the sorted arrays in an efficient way and keep the count of elements inserted in the output array or printed form. So when the elements in the output array are half the original size of the given array print the element as a median element. There are two cases:
    1. Case 1: m+n is odd, the median is at (m+n)/2 th index in the array obtained after merging both the arrays.
    2. Case 2: m+n is even, the median will be average of elements at index ((m+n)/2 – 1) and (m+n)/2 in the array obtained after merging both the arrays
  • Algorithm:
    1. Given two arrays are sorted. So they can be merged in O(m+n) time. Create a variable count to have a count of elements in the output array.
    2. If the value of (m+n) is odd then there is only one median else the median is the average of elements at index (m+n)/2 and ((m+n)/2 – 1).
    3. To merge the both arrays, keep two indices i and j initially assigned to 0. Compare the ith index of 1st array and jth index of second, increase the index of the smallest element and increase the count.
    4. Check if the count reached (m+n) / 2 if (m+n) is odd and store the element, if even store the average of (m+n)/2 th and (m+n)/2 -1 th element and print it.
  • Implementation:

    C++

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // A Simple Merge based O(n) solution to find 
    // median of two sorted arrays 
    #include <bits/stdc++.h>
    using namespace std;
      
    /* This function returns median of ar1[] and ar2[]. 
    Assumption in this function: 
    Both ar1[] and ar2[] are sorted arrays */
    int getMedian(int ar1[], int ar2[], int n, int m) 
        int i = 0; /* Current index of input array ar1[] */
        int j = 0; /* Current index of input array ar2[] */
        int count; 
        int m1 = -1, m2 = -1; 
      
        // Since there are (n+m) elements, 
        // There are following two cases 
        // if n+m is odd then the middle 
        //index is median i.e. (m+n)/2 
        if((m + n) % 2 == 1) 
        
            for (count = 0; count <= (n + m)/2; count++)
            
                if(i != n && j != m)
                
                    m1 = (ar1[i] > ar2[j]) ? ar2[j++] : ar1[i++]; 
                
                else if(i < n)
                
                    m1 = ar1[i++]; 
                
                // for case when j<m, 
                else
                
                    m1 = ar2[j++]; 
                
            
            return m1; 
        
          
        // median will be average of elements 
        // at index ((m+n)/2 - 1) and (m+n)/2 
        // in the array obtained after merging ar1 and ar2 
        else 
        
            for (count = 0; count <= (n + m)/2; count++) 
            
                m2 = m1; 
                if(i != n && j != m)
                
                    m1 = (ar1[i] > ar2[j]) ? ar2[j++] : ar1[i++]; 
                
                else if(i < n)
                
                    m1 = ar1[i++]; 
                
                // for case when j<m, 
                else
                
                    m1 = ar2[j++]; 
                
            
            return (m1 + m2)/2; 
        
      
    /* Driver code */
    int main() 
        int ar1[] = {900}; 
        int ar2[] = {5, 8, 10, 20}; 
      
        int n1 = sizeof(ar1)/sizeof(ar1[0]); 
        int n2 = sizeof(ar2)/sizeof(ar2[0]); 
        cout << getMedian(ar1, ar2, n1, n2); 
        return 0; 
      
    // This is code is contributed by rathbhupendra

    chevron_right

    
    

    C

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // A Simple Merge based O(n) solution to find 
    // median of two sorted arrays 
    #include <stdio.h> 
      
    /* This function returns median of ar1[] and ar2[]. 
    Assumption in this function: 
    Both ar1[] and ar2[] are sorted arrays */
    int getMedian(int ar1[], int ar2[], int n, int m) 
        int i = 0; /* Current index of input array ar1[] */
        int j = 0; /* Current index of input array ar2[] */
        int count; 
        int m1 = -1, m2 = -1; 
      
        // Since there are (n+m) elements, 
        // There are following two cases
        // if n+m is odd then the middle 
        //index is median i.e. (m+n)/2
        if((m + n) % 2 == 1) {
            for (count = 0; count <= (n + m)/2; count++) {
                if(i != n && j != m){
                m1 = (ar1[i] > ar2[j]) ? ar2[j++] : ar1[i++];
                }
                else if(i < n){
                m1 = ar1[i++];
                }
                // for case when j<m,
                else{
                m1 = ar2[j++];
                }
            }
            return m1;
        }
          
        // median will be average of elements 
        // at index ((m+n)/2 - 1) and (m+n)/2
        // in the array obtained after merging ar1 and ar2
        else {
            for (count = 0; count <= (n + m)/2; count++) {
                m2 = m1;
                if(i != n && j != m){
                m1 = (ar1[i] > ar2[j]) ? ar2[j++] : ar1[i++];
                }
                else if(i < n){
                m1 = ar1[i++];
                }
                // for case when j<m,
                else{
                m1 = ar1[j++];
                }
            }
            return (m1 + m2)/2;
        }
    }
      
    /* Driver program to test above function */
    int main() 
        int ar1[] = {900}; 
        int ar2[] = {5, 8, 10, 20}; 
      
        int n1 = sizeof(ar1)/sizeof(ar1[0]); 
        int n2 = sizeof(ar2)/sizeof(ar2[0]); 
        printf("%d", getMedian(ar1, ar2, n1, n2)); 
        getchar(); 
        return 0; 
    // This code is uploaded by Pratil

    chevron_right

    
    


    Output:



    10
  • Complexity Analysis:

    • Time Complexity: O(m + n).
      To merge both the arrays O(m+n) time is needed.
    • Space Complexity: O(1).
      No extra space is required.

Efficient solution:

  • Approach:The idea is simple, calculate the median of both the arrays and discard one half of each array.
    Now, there are some basic corner cases. For array size less than or equal to 2

    Suppose there are two arrays and the size of both the arrays is greater than 2.
    Find the middle element of the first array and middle element of the second array (the first array is smaller than the second) if the middle element of the smaller array is less than the second array, then it can be said that all elements of the first half of smaller array will be in the first half of the output (merged array). So, reduce the search space by ignoring the first half of the smaller array and the second half of the larger array. Else ignore the second half of the smaller array and first half of a larger array.

    In addition to that there are more basic corner cases:

    1. If the size of smaller array is 0. Return the median of a larger array.
    2. if the size of smaller array is 1.
      1. The size of the larger array is also 1. Return the median of two elements.
      2. If the size of the larger array is odd. Then after adding the element from 2nd array, it will be even so the median will be an average of two mid elements. So the element from the smaller array will affect the median if and only if it lies between (m/2 – 1)th and (m/2 + 1)th element of the larger array. So, find the median in between the four elements, the element of the smaller array and (m/2)th, (m/2 – 1)th and (m/2 + 1)th element of a larger array
      3. Similarly, if the size is even, then check for the median of three elements, the element of the smaller array and (m/2)th, (m/2 – 1)th element of a larger array
    3. If the size of smaller array is 2
      1. If the larger array also has two elements, find the median of four elements.
      2. If the larger array has an odd number of elements, then the median will be one of the following 3 elements
        1. Middle element of larger array
        2. Max of the first element of smaller array and element just before the middle, i.e M/2-1th element in a bigger array
        3. Min of the second element of smaller array and element
          just after the middle in the bigger array, i.e M/2 + 1th element in the bigger array
      3. If the larger array has even number of elements, then the median will be one of the following 4 elements
        1. The middle two elements of the larger array
        2. Max of the first element of smaller array and element just before the first middle element in the bigger array, i.e M/2 – 2nd element
        3. Min of the second element of smaller array and element just after the second middle in the bigger array, M/2 + 1th element

    How can one half of each array be discarded?

    Let’s take an example to understand this
    Input :arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
    brr[] = { 11, 12, 13, 14, 15, 16, 17, 18, 19 }
    Dry Run of the code:
    Recursive call 1:
    smaller array[] = 1 2 3 4 5 6 7 8 9 10, mid = 5
    larger array[] = 11 12 13 14 15 16 17 18 19 , mid = 15

    5 < 15
    Discard first half of the first array and second half of the second array

    Recursive call 2:
    smaller array[] = 11 12 13 14 15, mid = 13
    larger array[] = 5 6 7 8 9 10, mid = 7



    7 < 13
    Discard first half of the second array and second half of the first array

    Recursive call 3:
    smaller array[] = 11 12 13 , mid = 12
    larger array[] = 7 8 9 10 , mid = 8

    8 < 12
    Discard first half of the second array and second half of the first array

    Recursive call 4:
    smaller array[] = 11 12
    larger array[] = 8 9 10

    Size of the smaller array is 2 and the size of the larger array is odd
    so, the median will be the median of max( 11, 8), 9, min( 10, 12)
    that is 9, 10, 11, so the median is 10.

    Output:10.000000

  • Algorithm:
    1. Create a recursive function that takes two arrays and the sizes of both the arrays.
    2. Take care of the base cases for the size of arrays less than 2. (previously discussed in Approach).Note: The first array is always the smaller array.
    3. Find the middle elements of both the arrays. i.e element at (n – 1)/2 and (m – 1)/2 of first and second array respectively. Compare both the elements.
    4. If the middle element of the smaller array is less than the middle element of the larger array then the first half of smaller array is bound to lie strictly in the first half of the merged array. It can also be stated that there is an element in the first half of the larger array and second half of the smaller array which is the median. So, reduce the search space to the first half of the larger array and second half of the smaller array.
    5. Similarly, If the middle element of the smaller array is greater than the middle element of the larger array then reduce the search space to the first half of the smaller array and second half of the larger array.
  • Implementation:

    C++

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // A C++ program to find median of two sorted arrays of
    // unequal sizes
    #include <bits/stdc++.h>
    using namespace std;
      
    // A utility function to find median of two integers
    float MO2(int a, int b)
    { return ( a + b ) / 2.0; }
      
    // A utility function to find median of three integers
    float MO3(int a, int b, int c)
    {
        return a + b + c - max(a, max(b, c))
                         - min(a, min(b, c));
    }
      
    // A utility function to find a median of four integers
    float MO4(int a, int b, int c, int d)
    {
        int Max = max( a, max( b, max( c, d ) ) );
        int Min = min( a, min( b, min( c, d ) ) );
        return ( a + b + c + d - Max - Min ) / 2.0;
    }
      
    // Utility function to find median of single array
    float medianSingle(int arr[], int n)
    {
       if (n == 0)
          return -1;
       if (n%2 == 0)
            return (double)(arr[n/2] + arr[n/2-1])/2;
       return arr[n/2];
    }
      
    // This function assumes that N is smaller than or equal to M
    // This function returns -1 if both arrays are empty
    float findMedianUtil( int A[], int N, int B[], int M )
    {
        // If smaller array is empty, return median from second array
        if (N == 0)
          return medianSingle(B, M);
      
        // If the smaller array has only one element
        if (N == 1)
        {
            // Case 1: If the larger array also has one element,
            // simply call MO2()
            if (M == 1)
                return MO2(A[0], B[0]);
      
            // Case 2: If the larger array has odd number of elements,
            // then consider the middle 3 elements of larger array and
            // the only element of smaller array. Take few examples
            // like following
            // A = {9}, B[] = {5, 8, 10, 20, 30} and
            // A[] = {1}, B[] = {5, 8, 10, 20, 30}
            if (M & 1)
                return MO2( B[M/2], MO3(A[0], B[M/2 - 1], B[M/2 + 1]) );
      
            // Case 3: If the larger array has even number of element,
            // then median will be one of the following 3 elements
            // ... The middle two elements of larger array
            // ... The only element of smaller array
            return MO3( B[M/2], B[M/2 - 1], A[0] );
        }
      
        // If the smaller array has two elements
        else if (N == 2)
        {
            // Case 4: If the larger array also has two elements,
            // simply call MO4()
            if (M == 2)
                return MO4(A[0], A[1], B[0], B[1]);
      
            // Case 5: If the larger array has odd number of elements,
            // then median will be one of the following 3 elements
            // 1. Middle element of larger array
            // 2. Max of first element of smaller array and element
            //    just before the middle in bigger array
            // 3. Min of second element of smaller array and element
            //    just after the middle in bigger array
            if (M & 1)
                return MO3 ( B[M/2],
                             max(A[0], B[M/2 - 1]),
                             min(A[1], B[M/2 + 1])
                           );
      
            // Case 6: If the larger array has even number of elements,
            // then median will be one of the following 4 elements
            // 1) & 2) The middle two elements of larger array
            // 3) Max of first element of smaller array and element
            //    just before the first middle element in bigger array
            // 4. Min of second element of smaller array and element
            //    just after the second middle in bigger array
            return MO4 ( B[M/2],
                         B[M/2 - 1],
                         max( A[0], B[M/2 - 2] ),
                         min( A[1], B[M/2 + 1] )
                       );
        }
      
        int idxA = ( N - 1 ) / 2;
        int idxB = ( M - 1 ) / 2;
      
         /* if A[idxA] <= B[idxB], then median must exist in
            A[idxA....] and B[....idxB] */
        if (A[idxA] <= B[idxB] )
          return findMedianUtil(A + idxA, N/2 + 1, B, M - idxA );
      
        /* if A[idxA] > B[idxB], then median must exist in
           A[...idxA] and B[idxB....] */
        return findMedianUtil(A, N/2 + 1, B + idxA, M - idxA );
    }
      
    // A wrapper function around findMedianUtil(). This function
    // makes sure that smaller array is passed as first argument
    // to findMedianUtil
    float findMedian( int A[], int N, int B[], int M )
    {
        if (N > M)
           return findMedianUtil( B, M, A, N );
      
        return findMedianUtil( A, N, B, M );
    }
      
    // Driver program to test above functions
    int main()
    {
        int A[] = {900};
        int B[] = {5, 8, 10, 20};
      
        int N = sizeof(A) / sizeof(A[0]);
        int M = sizeof(B) / sizeof(B[0]);
      
        printf("%f", findMedian( A, N, B, M ) );
        return 0;
    }

    chevron_right

    
    

    PHP

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    <?php
    // A PHP program to find median 
    // of two sorted arrays of 
    // unequal sizes
      
    // A utility function to
    // find median of two integers
    function MO2($a, $b)
        return ($a + $b) / 2.0;
    }
      
    // A utility function to 
    // find median of three integers
    function MO3($a, $b, $c)
    {
        return $a + $b + $c
           max($a, max($b, $c)) -
           min($a, min($b, $c));
    }
      
    // A utility function to find
    // median of four integers
    function MO4($a, $b, $c, $d)
    {
        $Max = max($a, max($b, max($c, $d)));
        $Min = min($a, min($b, min( $c, $d)));
        return ($a + $b + $c + $d - $Max - $Min) / 2.0;
    }
      
    // Utility function to
    // find median of single array
    function medianSingle($arr, $n)
    {
    if ($n == 0)
        return -1;
    if ($n % 2 == 0)
            return ($arr[$n / 2] + 
                    $arr[$n / 2 - 1]) / 2;
    return $arr[$n / 2];
    }
      
    // This function assumes that N 
    // is smaller than or equal to M
    // This function returns -1 if
    // both arrays are empty
    function findMedianUtil(&$A, $N, &$B, $M )
    {
        // If smaller array is empty,
        // return median from second array
        if ($N == 0)
        return medianSingle($B, $M);
      
        // If the smaller array 
        // has only one element
        if ($N == 1)
        {
            // Case 1: If the larger
            // array also has one 
            // element, simply call MO2()
            if ($M == 1)
                return MO2($A[0], $B[0]);
      
            // Case 2: If the larger array 
            // has odd number of elements,
            // then consider the middle 3
            // elements of larger array and
            // the only element of smaller
            // array. Take few examples
            // like following
            // $A = array(9), 
            // $B = array(5, 8, 10, 20, 30) 
            // and $A = array(1),
            // $B = array(5, 8, 10, 20, 30)
            if ($M & 1)
                return MO2($B[$M / 2], $MO3($A[0], 
                           $B[$M / 2 - 1], 
                           $B[$M / 2 + 1]));
      
            // Case 3: If the larger array 
            // has even number of element,
            // then median will be one of 
            // the following 3 elements
            // ... The middle two elements
            //     of larger array
            // ... The only element of 
            //     smaller array
            return MO3($B[$M / 2], 
                       $B[$M / 2 - 1], $A[0]);
        }
      
        // If the smaller array
        // has two elements
        else if ($N == 2)
        {
            // Case 4: If the larger 
            // array also has two elements,
            // simply call MO4()
            if ($M == 2)
                return MO4($A[0], $A[1],
                           $B[0], $B[1]);
      
            // Case 5: If the larger array
            // has odd number of elements,
            // then median will be one of 
            // the following 3 elements
            // 1. Middle element of 
            //    larger array
            // 2. Max of first element of 
            //    smaller array and element
            // just before the middle 
            // in bigger array
            // 3. Min of second element 
            //    of smaller array and element
            // just after the middle 
            // in bigger array
            if ($M & 1)
                return MO3 ($B[$M / 2],
                            max($A[0], $B[$M / 2 - 1]),
                            min($A[1], $B[$M / 2 + 1]));
      
            // Case 6: If the larger array 
            // has even number of elements,
            // then median will be one of 
            // the following 4 elements
            // 1) & 2) The middle two 
            // elements of larger array
            // 3) Max of first element of 
            // smaller array and element
            // just before the first middle
            // element in bigger array
            // 4. Min of second element of 
            // smaller array and element
            // just after the second
            // middle in bigger array
            return MO4 ($B[$M / 2],
                        $B[$M / 2 - 1],
                        max($A[0], $B[$M / 2 - 2]),
                        min($A[1], $B[$M / 2 + 1]));
        }
      
        $idxA = ($N - 1 ) / 2;
        $idxB = ($M - 1 ) / 2;
      
        /* if $A[$idxA] <= $B[$idxB], then
            median must exist in
            $A[$idxA....] and $B[....$idxB] */
        if ($A[$idxA] <= $B[$idxB] )
        return findMedianUtil($A + $idxA
                              $N / 2 + 1, $B
                              $M - $idxA );
      
        /* if $A[$idxA] > $B[$idxB], 
        then median must exist in
        $A[...$idxA] and $B[$idxB....] */
        return findMedianUtil($A, $N/2 + 1, 
                              $B + $idxA, $M - $idxA );
    }
      
    // A wrapper function around
    // findMedianUtil(). This 
    // function makes sure that 
    // smaller array is passed as 
    // first argument to findMedianUtil
    function findMedian(&$A, $N
                        &$B, $M )
    {
        if ($N > $M)
        return findMedianUtil($B, $M
                              $A, $N );
      
        return findMedianUtil($A, $N
                              $B, $M );
    }
      
    // Driver Code
    $A = array(900);
    $B = array(5, 8, 10, 20);
      
    $N = sizeof($A);
    $M = sizeof($B);
      
    echo findMedian( $A, $N, $B, $M );
      
    // This code is contributed
    // by ChitraNayal
    ?>

    chevron_right

    
    


    Output:

     10 
  • Complexity Analysis:

    • Time Complexity: O(min(log m, log n)).
      In each step one half of each array is discarded. So the algorithm takes O(min(log m, log n)) time to reach the median value.
    • Space Complexity: O(1).
      No extra space is required.
  • Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

    Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




    My Personal Notes arrow_drop_up