1. 程式人生 > >【兩個有序陣列求中位數】

【兩個有序陣列求中位數】

/*
兩個有序陣列求中位數問題;
這個題有很多方法:
方法一:排序,找到中位數;
方法二:歸併排序的思想
方法三:轉換成求第k小值  
*/


/*
思路:使用二分查詢,時間複雜度為log(m+n). 該方法的核心是將原問題轉變成
一個尋找第k小數的問題(假設兩個原序列升序排列),
這樣中位數實際上是第(m+n)/2小的數。所以只要解決了第k小數的 問題,
原問題也得以解決。首先假設陣列A和B的元素個數都大於k/2,
我們比較A[k/2-1]和B[k/2-1]兩個元素,這兩個元素分別表示A的第k /2小的元素
和B的第k/2小的元素。這兩個元素比較共有三種情況:>、<和=。
如果A[k/2-1]<B[k/2-1],這表示 A[0]到A[k/2-1]的元素都在A和B合併之後的前k小的元素中。
換句話說,A[k/2-1]不可能大於兩數組合並之後的第k小值,所以我們可以將 其拋棄。
*/
#include<iostream>


using namespace std;


double findKth(int a[], int m, int b[], int n, int k)
{
if (m>n)
{
return findKth(b,n,a,m,k);
}


if (m==0)
{
return b[k-1];
}
if (k==1)
{
return min(a[0], b[0]);
}


int pa = min(k/2, m);
int pb = k - pa;
if (a[pa-1]<b[pb-1])
{
return findKth(a+pa, m-pa, b,  n, k-pa);
}
else if (a[pa-1]>b[pb-1])
{
return findKth(a, m, b+pb, n-pb, k-pb);
}
else
{
return a[pa-1];
}
}


class Solution
{
double findMedian(int A[], int m, int B[], int n)
{
int total = m + n;
if (total&0x1)
{
return findKth(A, m, B, n, total/2+1);
}
else
{
return (findKth(A, m, B, n, total / 2) + findKth(A,m,B,n,total/2+1))/2;
}
}
};