5.求两个有序数组的中位数
有两个有序数组A和B,其大小分别为m和n,求两个有序数的中间值
若m+n为偶数,则求两个中间数的平均值。
例:
A = { 1, 2, 3 };
B = { 4, 6, 7, 9, 11 };
Output:5.0
A = { 1, 2, 3 };
B = { 9, 11 };
Output:3.0
要求时间复杂度为O(log(m+n))
由于对时间复杂度有要求,因此不能直接遍历,可考虑分治法
假设数组A的中位数为m1,数组B为m2,例如:
ar1[] = {1,12, 15}
ar2[] = {2, 13, 17, 30, 45}
m1 = 12 ,m2 = 17 。由于m1<m2,则可以确定中位数即为下面两个子数组的中位数 :
[12,15] 和 [2, 13, 17]
重复这个步骤,可以得到 m1 = 15 m2 = 13.得到两个子数组:
[12, 15] 和[13, 17]
这时,由于n=2,无法在继续分下去了。可以直接计算得:
(13 + 15) / 2 = 14.0
Code:
public class test {
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);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] A = { 1, 12, 15 };
int[] B = { 2, 13, 17, 30, 45 };
double C = findMedianSortedArrays(A, B);
System.out.println(C);
}
}