There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
题解
这是一道非常经典的题。这题更通用的形式是,给定两个已经排序好的数组,找到两者所有元素中第k大的元素。这里要找的是中间值。如果m+n是奇数,返回中间值。如果是偶数,则返回直接两个数的和的一半。
最简单的做法,是按归并排序的做法,两个指针分别指向两个数组之首,然后逐一比较,取到中间值即可。所以时间复杂度是O((m+n)/2).
这个方法这里就不贴代码了。
下面讲的是类似二分法的方法,利用了数组有序的条件。
将k分为两个部分,设为k1和k2,然后比较nums1[k1-1]和nums2[k2-1],毫无疑问,较小的那部分肯定会被k选中(假设nums1[k1-1]较小),那么nums1中的前k1个数肯定是这k个数中的一部分。接下来重复操作,此时k=k-k1,然后nums1变成从第k1个数开始。
//cpp
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int k=nums1.size()+nums2.size();
if(k%2==1)
return find_kth(nums1,0,nums2,0,k/2+1);
else
return (find_kth(nums1,0,nums2,0,k/2)+find_kth(nums1,0,nums2,0,k/2+1))/2.0;
}
int find_kth(vector<int>& nums1,int n, vector<int>& nums2,int m,int k)//借助n、m来作为nums1和nums2的当前下标
{
if(nums1.size()-n<nums2.size()-m) return find_kth(nums2,m,nums1,n,k);//大的数组为1,小的为2
if(nums2.size()-m==0) return nums1[n+k-1];
if(k==1) return min(nums1[n],nums2[m]);
int len1=nums1.size()-n;
int len2=nums2.size()-m;
int k_in_2=min(k/2,len2);//设k2个数在nums2
int k_in_1=k-k_in_2;//设k1个数在nums1
//确定k1个数在nums1
if(nums1[n+k_in_1-1] < nums2[m+k_in_2-1])
return find_kth(nums1,n+k_in_1,nums2,m,k_in_2);
//确定k2个数在nums1
else if(nums1[n+k_in_1-1] > nums2[m+k_in_2-1])
return find_kth(nums1,n,nums2,m+k_in_2,k_in_1);
//恰好k1个数在nums1,k2个数在nums2
else return nums1[k_in_1-1];
}
};