1. 程式人生 > >2個有序陣列求合併後的中位數

2個有序陣列求合併後的中位數

原題:2個等長,有序陣列x[], y[],求2個數組合並後的中位數。

這裡有一個問題:2個長度為n的陣列,合併後長度為2n,那麼這個中位數是第n個呢,還是第n+1個呢?這點我也沒想明白,就按第n個算。

這個問題的實質,就是求合併後長度為2n的陣列中的第n個數。

方法一:合併2個有序陣列,比較次數是n+n.  其實我們沒必要完全排序這2個數組,只要排序前n個即可,只要的話比較次數剛好為n;

程式碼如下:

#include<iostream>
using namespace std;

int find(int *a,int *b,int len)
{
	int i = 0,j = 0;//分別指向a,b陣列的當前元素
    int count = 1;//因為i=j=0,已經開始計數第一個元素了
					//下一步無論哪一個++,都計數的是第二個元素,所以這裡count從開始計數

    while(count<len)
    {
         if(*(a+i)<=*(b+j))
         {
              i++;
         }else
         {
              j++;
         }
         count++;
    }
    return *(a+i);
}
int main()
{
    int a[] = {1,3,5,7,9};
    int b[] = {12,14,16,18,114};
    int len = sizeof(a)/sizeof(a[0]);
    int result = find(a,b,len);
    cout<<result<<endl;
    getchar();
    return 0;
}


方法二:二分法思想,複雜度應該是O(lgn)

首先比較陣列x,y的中間元素 x[n/2], y[n/2],

                a. 如果x[n/2] == y[n/2],那麼說明x[mid]就是第n大的數,也就是那個中位數。

                b. 如果x[n/2] > y[n/2],那麼說明y[0] - y[n/2]之間的n/2個數肯定在前n個數當中,而且中位數一定在x陣列的前半部分或者y陣列的後半部分,只要就轉換成在x數                           組的前半部分 和y陣列的後半部分找到第(n - n/2)大的元素,可以遞迴求解。

                c. 如果x[mid]<y[mid] 分析同上

程式碼如下:

#include<iostream>
using namespace std;

int find(int *a,int *b,int len)
{
    if(len == 1)
           return a[0];
    int mid = len/2;
    if(a[mid] == b[mid])
              return a[mid];
    if(a[mid] < b[mid]) //如果a[mid]較小,那麼說明a[0]-a[mid]肯定屬於合併後陣列前n大的數。
	{		//剩下的工作就是在a[mid]-a[n]或者,b[0]-b[mid]中找到第n-mid大的元素。
              return find(a+mid,b,len-mid);
    }
    else
    {       
              return find(a,b+mid,len-mid);
    }
}
int main()
{
    int a[] = {1,3,5,7,9};
    int b[] = {10,11,12,13,14};
    int len = sizeof(a)/sizeof(a[0]);
    int result = find(a,b,len);
    cout<<result<<endl;
    getchar();
    return 0;
}