題目描述:
計算兩個有序數組的中位數,至少一個數組不爲空。要求時間複雜度O(log(m+n)),m、n分別爲兩個數組的長度。
如:
{1,2} {3} 輸出應爲2
{1,3} {2,5} 輸出應爲2.5
題目分析:
時間複雜度要求爲log級別,數組又都是有序的,容易聯想到二分,每次比較去掉一部分元素。
數組中位數第一反應是需要分奇偶。奇數的話,我們只需要找到兩個數組長度的中間那個下標元素即可,偶數則需要求個平均,因此問題的關鍵轉化爲了查找兩數組的第k小元素。
第一個數組aa,第二個數組bb。找第k小元素,需要分別在兩個數組中找到某個元素(第a、b個元素),滿足a+b=k,且aa[a]>=bb[b-1]、bb[b]>=aa[a-1]。我們假設第一個數組長度小於第二個數組(否則交換下),如果前一個數組爲空,那直接去後者的第k個元素即可;如果k爲1(k不可能爲0,因爲題目規定至少一個數組不爲空),取兩數組第一個元素最小值即可(第一個數組長度小於第二個數組,因此第一個數組不爲空,後者也不會爲空);比較aa中第k/2的元素和滿足取k個元素的bb中對應的元素,較小的元素對應的數組的左半部分即可捨去(因爲它們肯定是前k-1小中的元素),捨去這a(或b)個元素的同時,我們的尋找目標就變成了再剩餘數組中找第k-a(或k-b)小元素。如此遞歸。
參考代碼:
#include<vector>
#include<iostream>
using namespace std;
//計算兩個已排好序的數組的中位數
double findMedianSortedArrays(vector<int>& a, vector<int>& b);
int main()
{
int a[] = {1,2};
int b[] = {3,5,5,5};
vector<int> nums1(a,a+sizeof(a)/sizeof(int));
vector<int> nums2(b,b+sizeof(b)/sizeof(int));
cout<<findMedianSortedArrays(nums1,nums2)<<endl;
return 0;
}
int findKth(vector<int>& aa, vector<int>& bb, int k)
{
int len1 = aa.size();
int len2 = bb.size();
if(len1>len2)
return findKth(bb,aa,k);
//注意:先判斷aa是否爲空
if(len1==0)
return bb[k-1];
if(k==1)
return min(aa[0],bb[0]);
int a = min(k/2,len1);
int b = k-a;
if(aa[a-1]<bb[b-1])
{
vector<int> m(aa.begin()+a,aa.end());
return findKth(m,bb,k-a);
}
else if(aa[a-1]>bb[b-1])
{
vector<int> m(bb.begin()+b,bb.end());
return findKth(aa,m,k-b);
}
else
return aa[a-1];
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2)
{
int len1 = nums1.size();
int len2 = nums2.size();
int k = (len1+len2)/2;
if((len1+len2)%2)
return findKth(nums1,nums2,k+1);
else
return (findKth(nums1,nums2,k+1)+findKth(nums1,nums2,k))/2.0;
}