兩個正序數組的中位數


兩個正序數組的中位數

給定兩個大小為 m 和 n 的正序(從小到大)數組 nums1 和 nums2。

請你找出這兩個正序數組的中位數,並且要求算法的時間復雜度為 O(log(m + n))。

你可以假設 nums1 和 nums2 不會同時為空。

解法一 雙指針

對於奇數個數,中位數一定為第(n+m)/2+1個
對於偶數個數,中位數一定在第(n+m)/2和(n+m)/2+1個
那么為了統一情況,應對奇數和偶數的情況,我們需要記錄兩個值,當前值和上一個值
代碼如下:

int l=0,r=0;
int left=-1,right=-1,len=(n+m);
for(int i=0;i<=len/2;i++)
{
   left=right;
   if(l<n&&(r>=m||nums1[l]<nums2[r])
       right=nums1[l++];
   else
       right=nums2[r++];
}
if(len&1)  return right;
else return (left+right)*0.5;

解法二--- 二分,找區間第k小數

思路是我們分別尋找兩個有序數組的第k/2個數,假設nums1[k/2]<nums2[k/2],那么可以推知nums1左半部分的數字都可以舍去,於是我們對新的區間重復上述動作,從而可以遞歸實現

 //獲得兩個數組的第k大的數
    int getk(vector<int>& nums1,int st1,int ed1,vector<int>& nums2,int st2,int ed2,int k)
    {
        int len1=ed1-st1+1;
        int len2=ed2-st2+1;
        if(len1>len2) return getk(nums2,st2,ed2,nums1,st1,ed1,k); //始終保持len1<len2
        if(len1==0)  return nums2[st2+k-1];  //一定是len1先為0
        if(k==1)  return min(nums1[st1],nums2[st2]);
        //尋找每個數組中第k/2個元素
        int i=st1+min(k/2,len1)-1;
        int j=st2+min(k/2,len2)-1;

        if(nums1[i]>nums2[j])  //此時nums2的st2左半部分可以刪除
            return getk(nums1,st1,ed1,nums2,j+1,ed2,k-(j-st2+1));
        else
            return getk(nums1,i+1,ed1,nums2,st2,ed2,k-(i-st1+1));
    }
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int n=nums1.size(),m=nums2.size();
        int left=(n+m+1)/2;
        int right=(n+m+2)/2;
        return  (getk(nums1,0,n-1,nums2,0,m-1,left)+getk(nums1,0,n-1,nums2,0,m-1,right))*0.5; 
}


免責聲明!

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



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