题目描述
给定两个大小为 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
步骤:
1.先确保m<=n,如果不满足 就把两者都交换(目的是为了使后面j总是>=0)
2.i作为nums1的标记,j作为nums2的标记,用halflen表示两个数组拼起来的一半长度,分为左边一半和右边的一半。
3.为了求中位数,那么就需要左边一半的max小于右边一半的min。如果nums1[i-1]>nums2[j],这里为保证两半长度是一样的,i就要增大,j相应的减小(这样把nums1中大的数放到右边,nums2的小的数放到左边,通过移动 i 这个标记来实现这个操作)。如果nums[j-1]>nums1[i],同理就是j要增大而i减小。
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m=nums1.size(),n=nums2.size();
if(m==0)
{
if(n%2==1)
return nums2[n/2];
return (nums2[n/2]+nums2[n/2-1])/2.0;
}
if(n==0)
{
if(m%2==1)
return nums1[m/2];
return (nums1[m/2]+nums1[m/2-1])/2.0;
}
if(m>n) //为了保证m<=n,如果m>n,就让两者交换
{
vector<int> num;
num=nums1;nums1=nums2;nums2=num;
int temp;
temp=m;m=n;n=temp;
}
int imin=0,imax=m, halflen=(m+n+1)/2;
int lmax=0,rmin=0;
while(imin<=imax)
{
int i=(imin+imax)/2; //nums1的标记
int j=halflen-i; //nums2的标记
if(i<m & nums2[j-1]>nums1[i])
{
imin=i+1;
}
else if(i>0 & nums1[i-1]>nums2[j])
imax=i-1;
else
{
if(i==0)
lmax=nums2[j-1];
else if(j==0)
lmax=nums1[i-1];
else
lmax=max(nums1[i-1],nums2[j-1]);
if((m+n)%2==1)
return lmax;
if (i==m)
rmin=nums2[j];
else if(j==n)
rmin=nums1[i];
else
rmin=min(nums1[i],nums2[j]);
return (lmax+rmin)/2.0;
}
}
}
};
方法二:这个思路更简单了
这个方法先建立一个res数组,
将小的数先放入res中,当其中一个数组中的数都放完了之后,把另一个数组中未存入的数组补齐放入res中
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m=nums1.size(),n=nums2.size();
if(m==0)
{
if(n%2==1)
return nums2[n/2];
return (nums2[n/2]+nums2[n/2-1])/2.0;
}
if(n==0)
{
if(m%2==1)
return nums1[m/2];
return (nums1[m/2]+nums1[m/2-1])/2.0;
}
vector<int> res;
int i=0,j=0;
while(i<m&&j<n) //将小的数先存入res中
{
if(nums1[i]<=nums2[j])
{
res.push_back(nums1[i]);
i++;}
else
{
res.push_back(nums2[j]);
j++;}
}
while(i<m) //也就是当经过上述j=n后,如果nums1中的数组还未存放完继续放入res中
{
res.push_back(nums1[i]);
i++;
}
while(j<n)
{
res.push_back(nums2[j]);
j++;
}
int len=m+n;
if(len%2==1)
return res[len/2]*1.0;
else
return (res[len/2]+res[len/2-1])/2.0;
}
};