4. Median of Two Sorted Arrays
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)).
分析
寻找两个已排序序列的中位数,中位数就是一个序列中位置中间的那个数,当元素个数为奇数时,中位数就是第n/2
个元素;当元素个数为偶数时,中位数就是第n/2
个元素和第 n/2 + 1
个元素的平均值;
最直接的方法就是合并两个有序序列,然后找到第k
大元素。这种方法的时间复杂度为O(k).
另一种法就是利用二分法思想(排序后是序列都很有可能利用二分法思想)。我们可以考虑从k
入手,如果每次都可以删除一个一定在第k大元素之前的元素,那么需要进行k
次。但是如果一次删除一半呢?优于两个序列是有序的,我么可以充分利用这部分信息。
假设A序列和B序列的元素个数都大于k/2
,比较A[K/2-1]
和B[K/2-1]
有三种情况:
A[K/2-1] = B[K/2-1]
A[K/2-1] > B[K/2-1]
A[K/2-1] < B[K/2-1]
如果A[K/2-1] < B[K/2-1]
,则A[0]
到A[K/2-1]
肯定在A
、B
集合的前k
大元素范围,因此可以放心删除A
序列里的这k/2
个元素;
当A[K/2-1] > B[K/2-1]
时,可以删除B
序列里的前k/2
个元素
当A[K/2-1] > B[K/2-1]
时,说明找到了第`k大元素。
因此可以通过递归函数来解决,递归的终止条件就是:
当A
或B
为空时,直接返回B[k-1]
或者A[k-1]
当k=1
时,返回min(A[0],B[0])
当A[K/2-1] = B[K/2-1]
时,返回A[K/2-1]
或者 B[K/2-1]
源码
方法1:合并排序然后遍历
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
double ret = 0;
int total = nums1.size() + nums2.size();
int m = 0, n = 0, count = 0;
int k = total / 2;
int a = 0, b = 0, tmp = 0;
while(count <= k) {
if(m >= nums1.size()) {
tmp = nums2[n];
n++;
} else if(n >= nums2.size()) {
tmp = nums1[m];
m++;
} else if(nums1[m] <= nums2[n]) {
tmp = nums1[m];
m++;
} else {
tmp = nums2[n];
n++;
}
count++;
a = b;
b = tmp;
}
if(total % 2 == 0) {
return (a + b) / 2.0;
} else {
return b;
}
}
方法二:二分递归
double findKth(int a[], int m, int b[], int n, int k)
{
if (m > n) // 总是假设a数组比b数组短
return findKth(b, n, a, m, k);
if (m == 0) // 短数组a的元素个数为0时直接返回长数组b中的第k大元素
return b[k - 1];
if (k == 1) // k=1时直接返回两个数组中首元素中的较小值
return min(a[0], b[0]);
//将k拆成两部分
int pa = min(k / 2, m), pb = k - pa;
if (a[pa - 1] < b[pb - 1]) //a[0]...a[pa-1]一定在第k大元素的前面,后面只需要考察a[pa]...
return findKth(a + pa, m - pa, b, n, k - pa);
else if (a[pa - 1] > b[pb - 1])//b[0]...b[pb-1]一定在第k大元素的前面,后面只需要考察b[pb]...
return findKth(a, m, b + pb, n - pb, k - pb);
else
return a[pa - 1];
}
double _findMedianSortedArrays(int A[], int m, int B[], int n)
{
int total = m + n;
if (total & 0x1) //元素个数为奇数
return findKth(A, m, B, n, total / 2 + 1);
else // 元素个数为偶数
return (findKth(A, m, B, n, total / 2)
+ findKth(A, m, B, n, total / 2 + 1)) / 2;
}
class Solution
{
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
return _findMedianSortedArrays(&nums1[0], nums1.size(), &nums2[0], nums2.size());
}
}