问题描述
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)).
Example 1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
算法分析
考察例子:
nums1[5]: 1 3 5 7 9
nums2[7]: 2 4 6 8 10 12 14
1、题目要求算法复杂度为log(m+n)
,所以肯定不能考虑合并这两个数组;
2、考虑二分查找,考虑到已经排序,令k=(5+7)/2+1
,比较nums1[k/2 - 1]
和nums2[k-k/2-1]
的大小,在这里即nums1[2]<nums2[3]
,所以中位数肯定不在nums[2]
的前一段。下一次就可以在nums1[3:5]
和nums2[0:7]
中查找,同时可以确定找到三个数nums[0:2]
小于中位数,故更新k=k-3
;
3、k可以理解为比中位数小的数的数量,每次数组的一段被排除,这一段即小于中位数。k大于1的时候递归上述查找过程,当k等于1的时候,比中位数小的数的数量达到,即找到中间值。
*值得注意的是,两个数组的长度之和为偶数时,需要查找得到两个中位数,取平均。
C++实现
class Solution {
typedef vector<int>::iterator Iter;
int findMedianCore(Iter start1, int len1, Iter start2, int len2, int k) {
if (len1 > len2)
return findMedianCore(start2, len2, start1, len1, k);
if (len1 == 0)
return *(start2 + k - 1);
if (k == 1)
return min(*start1, *start2);
int i1 = min(len1, k / 2);
int i2 = k - i1;
if ( *(start1 + i1 - 1) > *(start2 + i2 - 1) )
return findMedianCore(start1, len1, start2 + i2, len2 - i2, k - i2);
return findMedianCore(start1 + i1, len1 - i1, start2, len2, k - i1);
}
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int len1 = nums1.size();
int len2 = nums2.size();
if (!len1 && !len2)
return 0;
int k = (len1 + len2) / 2;
int result1 = findMedianCore(nums1.begin(), len1, nums2.begin(), len2, k + 1);
if ((len1 + len2) % 2 == 0) {
int result2 = findMedianCore(nums1.begin(), len1, nums2.begin(), len2, k);
return (double) (result1 + result2) / 2;
}
return result1;
}
};
算法复杂度为O( log(m+n) ).