計算兩個有序數組的中位數(C++)

題目描述: 

計算兩個有序數組的中位數,至少一個數組不爲空。要求時間複雜度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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章