原文地址: Median of Two Sorted Arrays
有两个排序数组A和B大小分别为m和n。找到两个排序数组的中值。整个运行时复杂度应该是O(log(m + n))。
Java 解决方案1
这个问题可以转化为找到第k个元素的问题,k是(A的长度+ B的长度)/ 2。
如果两个数组中的任何一个都是空的,那么第k个元素就是非空数组的第k个元素。如果k == 0,第k个元素是A或B的第一个元素。
对于一般情况(所有其他情况),我们需要将指针移动到数组大小的一半以获得时间log(n)。
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int total = nums1.length+nums2.length;
if(total%2==0){
return (findKth(total/2+1, nums1, nums2, 0, 0)+findKth(total/2, nums1, nums2, 0, 0))/2.0;
}else{
return findKth(total/2+1, nums1, nums2, 0, 0);
}
}
public int findKth(int k, int[] nums1, int[] nums2, int s1, int s2){
if(s1>=nums1.length)
return nums2[s2+k-1];
if(s2>=nums2.length)
return nums1[s1+k-1];
if(k==1)
return Math.min(nums1[s1], nums2[s2]);
int m1 = s1+k/2-1;
int m2 = s2+k/2-1;
int mid1 = m1<nums1.length?nums1[m1]:Integer.MAX_VALUE;
int mid2 = m2<nums2.length?nums2[m2]:Integer.MAX_VALUE;
if(mid1<mid2){
return findKth(k-k/2, nums1, nums2, m1+1, s2);
}else{
return findKth(k-k/2, nums1, nums2, s1, m2+1);
}
}
时间是O(log(k)).
Java 解决方案2
实际上,我们可以用多种不同的方式来编写二进制搜索解决方案。下面是其中一个:
public static double findMedianSortedArrays(int A[], int B[]) {
int m = A.length;
int n = B.length;
if ((m + n) % 2 != 0) // odd
return (double) findKth(A, B, (m + n) / 2, 0, m - 1, 0, n - 1);
else { // even
return (findKth(A, B, (m + n) / 2, 0, m - 1, 0, n - 1)
+ findKth(A, B, (m + n) / 2 - 1, 0, m - 1, 0, n - 1)) * 0.5;
}
}
public static int findKth(int A[], int B[], int k,
int aStart, int aEnd, int bStart, int bEnd) {
int aLen = aEnd - aStart + 1;
int bLen = bEnd - bStart + 1;
// Handle special cases
if (aLen == 0)
return B[bStart + k];
if (bLen == 0)
return A[aStart + k];
if (k == 0)
return A[aStart] < B[bStart] ? A[aStart] : B[bStart];
int aMid = aLen * k / (aLen + bLen); // a's middle count
int bMid = k - aMid - 1; // b's middle count
// make aMid and bMid to be array index
aMid = aMid + aStart;
bMid = bMid + bStart;
if (A[aMid] > B[bMid]) {
k = k - (bMid - bStart + 1);
aEnd = aMid;
bStart = bMid + 1;
} else {
k = k - (aMid - aStart + 1);
bEnd = bMid;
aStart = aMid + 1;
}
return findKth(A, B, k, aStart, aEnd, bStart, bEnd);
}