题目:找到两个排序数组的中位数, 两个数组大小分别是m和n, 要求时间复杂度是O(log(m+n))
中位数:数组长度是奇数,则中位数是中间值;数组长度是偶数,则中位数是中间两个数的算术平均值
例如:nums1 = [1, 3], nums2 = [2], 则中位数是2;nums1 = [1, 2], nums2 = [3, 4], 则中位数是(2+3)/2 = 2.5.
此题的核心思想是找到两个数组的第K大的数,具体到这个题,则是找到第(m+n+1)/2,以及第(m+n+2)/2,然后求他们的平均值
找两个排序数组第K大元素C++程序如下:
//两个数组A和B,la和lb分别表示数组的比较起始点,k表示需要寻找的顺序k
int findKth(vector<int>& A,int la, vector<int>& B, int lb,int k){
if(A.size()-la<B.size()-lb)
return findKth(B, lb, A, la, k); //将较长的数组放在前面
if(lb == B.size()) return A[la+k-1];
if(k==1) return min(A[la], B[lb]);
int kb = k/2<B.size()-lb?k/2:B.size()-lb;
int ka = k - kb;
if(A[la+ka-1]<B[lb+kb-1]){
return findKth(A, la+ka, B, lb, k-ka);
}else
return findKth(A, la, B, lb+kb, k-kb);
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int N1 = nums1.size();
int N2 = nums2.size();
if (N1 < N2) return findMedianSortedArrays(nums2, nums1); // Make sure A2 is the shorter one.
if (N2 == 0) return ((double)nums1[(N1-1)/2] + (double)nums1[N1/2])/2; // If A2 is empty
int lo = 0, hi = N2 * 2;
while (lo <= hi) {
int mid2 = (lo + hi) / 2; // Try Cut 2
int mid1 = N1 + N2 - mid2; // Calculate Cut 1 accordingly
double L1 = (mid1 == 0) ? INT_MIN : nums1[(mid1-1)/2]; // Get L1, R1, L2, R2 respectively
double L2 = (mid2 == 0) ? INT_MIN : nums2[(mid2-1)/2];
double R1 = (mid1 == N1 * 2) ? INT_MAX : nums1[(mid1)/2];
double R2 = (mid2 == N2 * 2) ? INT_MAX : nums2[(mid2)/2];
if (L1 > R2) lo = mid2 + 1; // A1's lower half is too big; need to move C1 left (C2 right)
else if (L2 > R1) hi = mid2 - 1; // A2's lower half too big; need to move C2 left.
else return (max(L1,L2) + min(R1, R2)) / 2; // Otherwise, that's the right cut.
}
return -1;
}