寻找两个有序数组的中位数
题目
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
样例
- nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0 - nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
Code
分析
通过两个数组元素总数(total)与十六进制1(0x1)进行按位与计算,判断total是奇数还是偶数。
假设A和B的元素个数都大雨k/2,将A的第k/2个元素(即A[k/2-1])和B的第k/2个元素(即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]的元素肯定在TOPk元素范围内,可以删除A中的前k/2个元素;
如果A[k/2-1] > B[k/2-1],则B[0]到B[k/2-1]的元素肯定在TOPk元素范围内,可以删除B中的前k/2个元素;
如果A[k/2-1] == B[k/2-1],则找到第k大的元素,直接返回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]。
时间复杂度O(log(m+n)),空间复杂度O(log(m+n))
double findMedianSortedArrays(vector<int>& A, vector<int>& B) {
const int m=A.size();
const int n=B.size();
int total=m+n;
if(total & 0x1) {
return find_kth(A.begin(), m, B.begin(), n, total/2+1);
} else {
return (find_kth(A.begin(), m, B.begin(), n, total/2)+find_kth(A.begin(), m, B.begin(), n, total/2+1))/2.0;
}
}
static int find_kth(std::vector<int>::const_iterator A,int m,std::vector<int>::const_iterator B,int n,int k) {
if(m>n) {
return find_kth(B,n,A,m,k);
}
if(m==0) {
return *(B+k-1);
}
if(k==1) {
return min(*A,*B);
}
int ia=min(k/2,m),ib=k-ia;
if(*(A+ia-1)<*(B+ib-1)) {
return find_kth(A+ia,m-ia,B,n,k-ia);
} else if(*(A+ia-1)>*(B+ib-1)) {
return find_kth(A,m,B+ib,n-ib,k-ib);
} else {
return A[ia-1];
}
}
若有疑问欢迎评论!