https://leetcode-cn.com/problems/median-of-two-sorted-arrays/
思路一:双指针
O
(
n
)
O(n)
O(n)合并两个有序数组。
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n=nums1.size();
int m=nums2.size();
int need=((n+m)>>1)+1,l=0,r=0;
bool odd=(n+m)&1;
vector<int> vec(need);
while(need)
{
if(l==n||(r!=m&&nums1[l]>nums2[r]))
vec[--need]=nums2[r++];
else
vec[--need]=nums1[l++];
}
return odd?vec[0]:(vec[0]+vec[1])/2.0;
}
};
思路二:二分。假设要找到两个序列内第 k k k小的元素,可以比较 a [ k / 2 − 1 ] a[k/2-1] a[k/2−1]和 b [ k / 2 − 1 ] b[k/2-1] b[k/2−1]:
- 前者小于后者,那么最多有k-1个元素小于或等于a [ k / 2 − 1 ] [k /2-1] [k/2−1],因此可以排除 a [ 0 … k / 2 − 1 ] a[0…k/2-1] a[0…k/2−1]。
- 后者小于前者,同理可以排除 b [ 0 … k / 2 − 1 ] b[0…k/2-1] b[0…k/2−1]。
- 前者等于后者,可以归入上述两种情况的任意一种处理。
每次可以排除一半的元素,因此这个算法的复杂度是 l o g log log的。不过还有一些细节需要考虑,比如到达每个数组的末尾,或者 k = 1 k=1 k=1。
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n=nums1.size(),m=nums2.size(),mid=((n+m)>>1)+1;
if((n+m)&1)
return getkth_element(nums1,nums2,0,0,mid);
else
return (getkth_element(nums1,nums2,0,0,mid-1)+getkth_element(nums1,nums2,0,0,mid))/2.0;
}
int getkth_element(vector<int> &a,vector<int> &b,int idx1,int idx2,int k)
{
int n=a.size(),m=b.size();
if(idx1==n)
return b[idx2+k-1];
else if(idx2==m)
return a[idx1+k-1];
else if(k==1)
return min(a[idx1],b[idx2]);
int k2=k>>1;
int nidx1=min(idx1+k2-1,n-1),nidx2=min(idx2+k2-1,m-1);
if(a[nidx1]<=b[nidx2])
return getkth_element(a,b,nidx1+1,idx2,k-nidx1-1+idx1);
else
return getkth_element(a,b,idx1,nidx2+1,k-nidx2-1+idx2);
}
};