求兩個有序數組的中位數-算法導論


Question

There are 2 sorted arrays A and B of size n each. Write an algorithm to find the median of the array obtained after merging the above 2 arrays(i.e. array of length 2n). The complexity should be O(log(n))。

有兩個排序的數組,長度都為n,求合並后的排序數組的中位數。

題目是《算法導論》上的一道習題,不過已多次出現在面試題當中。注意,此題中兩個數組的長度是相等的。當然,長度不等的話也可以做,只是要多些判斷條件。參考leetcode題目 Median of Two Sorted Arrays

方法1 直接遍歷

直接的解法是遍歷兩個數組並計數,類似歸並排序里面的有序數組的合並,復雜度為O(n)。代碼如下:

#include <iostream>
#include <stdio.h>
using namespace std;

double getMedian(int arr1[],int arr2[], int n)

{
     int i=0,j=0; //分別是 arr1, arr2的當前下標
     int m1=-1,m2=-1; //保存兩個中位數. 由於是2n個,肯定有兩個中位數
     for(int cnt=0; cnt<=n; cnt++)

     {
          if( i<n && (arr1[i] < arr2[j] || j >= n ))

          {
                 m1 = m2;
                 m2 = arr1[i++];
          }

         else

          {
                  m1 = m2;
                m2 = arr2[j++];
         }
    }
    return (m1+m2)/2.0;
}


int main()
{
      int ar1[] = {1, 12, 15, 26, 38};
     int ar2[] = {2, 13, 17, 30, 45};

     int n1 = sizeof(ar1)/sizeof(ar1[0]);
    int n2 = sizeof(ar2)/sizeof(ar2[0]);
    if (n1 == n2)
    printf("Median is %lf", getMedian(ar1, ar2, n1));
    else
    printf("Doesn't work for arrays of unequal size");
    return 0;
}

 

方法2 分治法

要求的復雜度為O(log (m+n)),很顯然需要用分治法求解。

假設數組A的中位數為m1,數組B為m2,例如:

ar1[] = {1, 12, 15, 26, 38}
ar2[] = {2, 13, 17, 30, 45}

m1 = 15 ,m2 = 17 。由於m1<m2,則可以確定中位數即為下面兩個子數組的中位數 :

[15, 26, 38]  和 [2, 13, 17]

重復這個步驟,可以得到   m1 = 26 m2 = 13. 得到兩個子數組:

[15, 26] 和[13, 17]

這時,由於n=2,無法在繼續分下去了。可以直接計算得:

median = (max(ar1[0], ar2[0]) + min(ar1[1], ar2[1]))/2
= (max(15, 13) + min(26, 17))/2
= (15 + 17)/2
= 16

代碼如下:

int median(int arr[], int n)
{
     if (n%2 == 0)
     return (arr[n/2] + arr[n/2-1])/2;
     else
      return arr[n/2];
}

int getMedian(int ar1[], int ar2[], int n)

{
    int m1;
    int m2;
    if (n <= 0)
    return -1;
   if (n == 1)
   return (ar1[0] + ar2[0]) / 2;

   if (n == 2)
   return (max(ar1[0], ar2[0]) + min(ar1[1], ar2[1])) / 2;

   m1 = median(ar1, n);
   m2 = median(ar2, n);
   /* 相等可直接返回 */
   if (m1 == m2)
   return m1;
   if (m1 < m2)

   {
        if (n % 2 == 0)
        return getMedian(ar1 + n/2-1, ar2, n/2 + 1);
        else
        return getMedian(ar1 + n/2, ar2, n/2+1);
   }

   else

   {
        if (n % 2 == 0)
             return getMedian(ar2 + n/2-1, ar1, n/2+1);
        else
           return getMedian(ar2 + n/2, ar1, n/2+1);
    }
}

int main()
{
      int ar1[] = {1, 12, 10, 26, 38};
       int ar2[] = {2, 13, 17, 30, 45};

      int n1 = sizeof(ar1)/sizeof(ar1[0]);
       int n2 = sizeof(ar2)/sizeof(ar2[0]);
      if (n1 == n2)
           printf("Median is %d", getMedian(ar1, ar2, n1));
       else
          printf("Doesn't work for arrays of unequal size");
      return 0;
}

時間復雜度為 O(logn)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM