题目描述
2个有序数组(保证不能同时为空)长度分别为m,n;求他们的中位数。
要求时间复杂度O(long(m+n))
。
解题思路
题目的要求可以转述为求第k大个数,k可能为1个数,可能为2个数。
k=(m+n)/2
num1[k/2]
表示第一个数组的第k/2个数。num2[k/2]
表示第二个数组的第k/2个数。
下面进行分类讨论:
num1[k/2]
<num2[k/2]
,那么只需要比较num1(k/2+1,m)和num2(0,n),且去掉了k/2个数。num1[k/2]
>num2[k/2]
,那么只需要比较num2(k/2+1,n)和num1(0,m),且去掉了k/2个数。num1[k/2]
=num2[k/2]
,该值就是答案。
每一次的比较k要进行修改。因为已经排除了k/2个数。
上述讨论没有结果就继续执行(递归或者循环)。
注意:
- m+n为奇数,中位数1个。
- m+n为偶数,中位数2个。
1个就找1遍,2个就找 2遍即可。
细节问题看具体的代码实现。
代码
cpp
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m=nums1.size(),n=nums2.size();
if((m+n)%2==0)
{
return (findMedian(nums1,nums2,0,0,(m+n)/2)+findMedian(nums1,nums2,0,0,(m+n)/2+1))/2.0;
}
else
{
return findMedian(nums1,nums2,0,0,(m+n)/2+1);
}
}
int findMedian(vector<int>& nums1, vector<int>& nums2,int sp1,int sp2,int k)
{
//保证nums1中要查找的元素个数小于nums2中的,是为了方便对边界进行处理。
if(nums1.size()-sp1>nums2.size()-sp2) return findMedian(nums2,nums1,sp2,sp1,k);
//当k位1的时候,就是两个数组中第一个元素中的最小值
if(k==1)
{
if(nums1.size()==sp1) return nums2[sp2];
return min(nums1[sp1],nums2[sp2]);
}
//因为第一个数组查找的数据较小 ,容易越界
if(nums1.size()==sp1) return nums2[sp2+k-1];
//第一个数组,当越界的时候,只需要比较较小值即可。
int i=min(sp1+k/2-1,(int)nums1.size()-1),j=sp2+k-k/2-1;
if(nums1[i]<nums2[j]) return findMedian(nums1,nums2,i+1,sp2,k-(i-sp1+1));
else return findMedian(nums1,nums2,sp1,j+1,k-(j-sp2+1));
}
};