Median of Two Sorted Arrays
There are two sorted arrays A and B 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)).
tag: divide and conquer, array, binary search
9/22/2015 update
Rewrite it in c++ version.
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int len = nums1.size() + nums2.size();
if(len % 2 == 0){
return (findKth(nums1, 0, nums1.size(), nums2, 0, nums2.size(), len / 2 - 1) + findKth(nums1, 0, nums1.size(), nums2, 0, nums2.size(), len / 2)) / 2;
}
else{
return findKth(nums1, 0, nums1.size(), nums2, 0, nums2.size(), len / 2);
}
}
double findKth(vector<int>& nums1, int start1, int end1, vector<int>& nums2, int start2, int end2, int k){
if(end1 - start1 > end2 - start2){
//ensures nums1 is shorter than nums2
return findKth(nums2, start2, end2, nums1, start1, end1, k);
}
//base case
if(end1 - start1 == 0){
return nums2[start2 + k];
}
if(k == 0){
return min(nums1[start1], nums2[start2]);
}
int pa = min(k/2 + start1, end1 - 1);//nums1[pa] is always available
int pb = start2 + k - (pa - start1 + 1);//same to nums2
if(nums1[pa] == nums2[pb]){
//happy
return nums1[pa];
}
else if(nums1[pa] < nums2[pb]){
//median is in the right part of nums1 and left part of nums2
//nums1[pa] can't be the result but nums2[pb] can
//PREVIOUS BUG HRER
return findKth(nums1, pa + 1, end1, nums2, start2, pb + 1, k - (pa - start1 + 1));
}
else{
//median is in the left part of nums1 and right part of nums2
//nums2[pb] can not be the result but nums1[pa] can
//BUG HERE
return findKth(nums1, start1, pa + 1, nums2, pb + 1, end2, k - (pb - start2 + 1));
}
}
};
挺难的题,我也是看了攻略才解出来。
这里阐述推广到在两个Sorted Arrays中找第k个数的算法。
1. 主函数中判断两个数组的长度和的奇偶性,根据中位数的定义来分清况调用递归函数。
2. 递归函数中,先保持m<n。然后将k平均分为两半pa,pb,在A和B中分别找第pa个数和第pb个数。如果两数相等,返回该值。
3. 如果A[pa – 1] > B[pb – 1],则说明解在A的左半部分或B的右半部分,我们可以排除掉B的左半部分,所以k = k – pb
4. 如果A[pa – 1] < B[pb – 1],则说明解在A的右半部分或B的左半部分,我们可以排除掉A的左半部分,所以k = k – pa
5. 注意处理递归到叶子节点时的情况,并要保持索引值小于M。
6. 时刻牢记,k指的是第k个值,而不是数组索引值(index),在做运算时要考虑加一减一的问题。
class Solution {
public:
double findMedianSortedArrays(int A[], int m, int B[], int n) {
int length = m + n;
if (length & 0x1){//odd
return findKth(A, m, B, n, (length + 1) / 2);
}
else{//even
return (findKth(A, m, B, n, length / 2) +
findKth(A, m, B, n, length / 2 + 1)) / 2;
}
}
double findKth(int A[], int m, int B[], int n, int k){//k = 1,2,3...
if(m > n){//keep m < n
return findKth(B, n, A, m, k);
}
else if(m == 0){
return B[k - 1];
}
else if(k == 1){
return min(A[0], B[0]);
}
else{
int pa = min(k/2, m);
int pb = k - pa;
if(A[pa - 1] == B[pb - 1]){
return A[pa - 1];
}
else if(A[pa - 1] > B[pb - 1]){//result lies in the right part of B, the left part of A
return findKth(A, pa, B + pb, n - pb, k - pb);
}
else{//A[pa - 1] < B[pb - 1]
return findKth(A + pa, m - pa, B, pb, k - pa);
}
}
}
};
