给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 。
请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log (m+n)) 。
你可以假设 nums1 和 nums2 不同时为空。
示例 1:
nums1 = [1, 3] nums2 = [2] 中位数是 2.0
示例 2:
nums1 = [1, 2] nums2 = [3, 4] 中位数是 (2 + 3)/2 = 2.5
二分查找nums1当中的数x,记录小于x的数(下标就可以做),然后用x在nums2当中做二分查找,找到小于x的个数。看看两个数组中小于x的数量是否刚好一半
两次二分,复杂度是O(logN*logM)看起来高于标准答案的O(log(N+M)),但是实际代码执行时间慢不了多少,原因在于很少有数据会真的到达最坏复杂度,大部分很快就能找到答案
我的解法的特殊情况极多,需要加很多分支来判断各种情况的处理。
需要考虑l1+l2是奇数还是偶数,要用不同的方案进行处理
需要考虑数组中有很多相同数据时该如何处理
具体可以看我代码,执行时间36ms
class Solution{
public:
double findMedianSortedArrays(vector<int>& nums1,vector<int>& nums2)
{
int n=nums1.size();
int m=nums2.size();
int left,right,mid;
if((n+m)%2==1)
{
left=0,right=n-1;
while(left<=right)
{
mid=(left+right)/2;
int lower_num=lower_bound(nums2.begin(),nums2.end(),nums1[mid])-nums2.begin();
int upper_num=upper_bound(nums2.begin(),nums2.end(),nums1[mid])-nums2.begin();
int a=lower_num+mid+1,b=upper_num+mid+1;
if(a>(m+n)/2+1)
right=mid-1;
else if(b<(m+n)/2+1)
left=mid+1;
else
return nums1[mid];
}
return findMedianSortedArrays(nums2,nums1);
}
else
{
double x,y,flag=true;
left=0,right=n-1;
while(left<=right)
{
mid=(left+right)/2;
int lower_num=lower_bound(nums2.begin(),nums2.end(),nums1[mid])-nums2.begin();
int upper_num=upper_bound(nums2.begin(),nums2.end(),nums1[mid])-nums2.begin();
int a=lower_num+mid+1,b=upper_num+mid+1;
if(a>(m+n)/2+1)
right=mid-1;
else if(b<(m+n)/2)
left=mid+1;
else
{
if(a<=(m+n)/2 && b>=(m+n)/2+1)
return nums1[mid];
else
{
if(a==(m+n)/2+1)
{
if(mid==0)
return (nums1[mid]+nums2[lower_num-1])/2.0;
else if(lower_num==0)
return (nums1[mid]+nums1[mid-1])/2.0;
else
return (nums1[mid]+max(nums1[mid-1],nums2[lower_num-1]))/2.0;
}
if(b==(m+n)/2)
{
if(mid==n-1)
return (nums1[mid]+nums2[upper_num])/2.0;
else if(upper_num==m)
return (nums1[mid]+nums1[mid+1])/2.0;
else
return (nums1[mid]+min(nums1[mid+1],nums2[upper_num]))/2.0;
}
}
}
}
return findMedianSortedArrays(nums2,nums1);
}
return 0;
}
};