https://leetcode-cn.com/problems/median-of-two-sorted-arrays/
给定两个大小为 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
题意为:
要求两个有序数组的中位数,且时间复杂度要求在O(log(m+n))内。
思路:
由于时间复杂度的原因,我们不难想到要用二分;
我们假设两个数组分别s1,s2,长度分别为n,m,将连个数组都切成两半,分别有s1左,s1右,s2左,s2右表示;
用Lmax1表示s1左的最大值,Lmin1表示s1右的最小值,Lmax2表示s2左的最小值,Lmin2表示s2右的最小值;
判断是否是中位数的根据为:
(1)Lmin1<=Lmax2 && Lmin2<=Lmax1
(2)i+j=m+n-i-j
根据中位数的性质,len(s1左)+len(s2左)==len(s1右)+len(s2右);
所以假设在s1中切得位置下标为i,那么在s2中切的下表对应为j=((n+m)/2-i);
至此可以针对s1数组做二分,有了s1的下标,s2的下表也对应可以求出;
这里再加入一个tricks,因为奇偶的关系,我们将数组插入#,那么s1,s2的长度变为2n+1,2m+1;求原坐标就是除以2即可;
判断是否为中位数的条件变为:
限制条件如下:
Lmax1= i==0? INT_MIN:s1[(i-1)/2]
Lmin1= i==2n? INT_MAX:s1[i/2]
Lmax2= j==0? INT_MIN:s2[(j-1)/2]
Lmin2= j==2n? INT_MAX:s2[j/2]
总体来说有一些难度,主要是限定条件分清楚。
代码如下:
class Solution {
public:
double binary_find(vector<int>& nums1,vector<int>& nums2)
{
int len1=nums1.size(),len2=nums2.size();
if(len1>len2)
{
return binary_find(nums2,nums1);
}
int Lmin1,Lmax1,Lmin2,Lmax2,lo=0,hi=2*len1;
int i,j;
while(lo<=hi)
{
i=(lo+hi)/2;
j=len1+len2-i;
Lmax1=i==0?INT_MIN:nums1[int((i-1)/2)];
Lmin1=i==2*len1?INT_MAX:nums1[int(i/2)];
Lmax2=j==0?INT_MIN:nums2[int((j-1)/2)];
Lmin2=j==2*len2?INT_MAX:nums2[int(j/2)];
if(Lmax1<=Lmin2&&Lmax2<=Lmin1)
break;
else if(Lmax1>Lmax2)
hi=i-1;
else if(Lmax2>Lmin1)
lo=i+1;
}
return (max(Lmax1,Lmax2)+min(Lmin1,Lmin2))/2.0;
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
return binary_find(nums1,nums2);
}
};