兩個正序陣列的中位數
阿新 • • 發佈:2020-09-21
兩個正序陣列的中位數
給定兩個大小為 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; }