import static java.
lang.
Math.
max; import static java.
lang.
Math.
min;
class KthLargestTwoArrays {
/**
* Given two sorted arrays of equal sizes, finds the median of the
* array that comes out after `a` and `b` being merged. Runs in
* linear time and does not require any extra space.
*
* The algorithm is similar to the arrays merging, but it
* does not save the merged array, it just iterates through both
* of them by n+1 items (thus stopping in the middle of an imaginary
* merged array) and memorizes two consecutive elements. These
* are the two elements laying exactly in the middle of merged array.
*
* (Since the length of the merged array is even, its median
* is an average value of two elements in the middle.)
*
* @param a a sorted array
* @param b a sorted array
*/
static double medianTwoArraysLinear(double[] a, double[] b) {
if (a.length != b.length) {
"Expected: len(a) == len(b)."
+ " Got: len(a) = %d, len(b) = %d",
a.length, b.length
));
}
final int n = a.length;
int i = 0, j = 0;
// two consecutive elements of the merged array
for (int k = 0; k < n + 1; k++) {
// here we also handle a special case when every element
// of the first array is smaller than the smallest element
// of the second array (and vice versa)
if (j == n || i < n && a[i] < b[j]) {
// put the previous value into the buffer
mid1 = mid2;
mid2 = a[i];
i++;
} else {
mid1 = mid2;
mid2 = b[j];
j++;
}
}
return (mid1 + mid2) / 2;
}
/**
* A logarithmic-time algorithm that solves the same problem.
* The basic idea is to compute the medians of both of the
* arrays (well, these are not exactly "medians", in case the
* array length is even, mid = A[n / 2], not the average value):
* A = [a1, a2, ..., mid1, ..., an]
* B = [b1, b2, ..., mid2, ..., bn]
* and after that there are three cases to consider:
*
* - mid1 == mid2, which means (given len(A) == len(B)) that
* in every array there are n/2 elemets on the left side
* from the mid, so in the merged array mid1 and mid2 would
* be on n/2 + n/2 = n and n+1 positions (thus mid1 is the
* median of the merged array)
*
* - mid1 < mid2 means that the greatest element of the left
* side of the array A (A_left) is at most as large as the
* greatest element of B_left. And similarly the smallest
* element of B_right is at least as large as the smallest
* element of A_right.
*
* This means that the left side of the imaginary merged array
* for sure would not end with an element from A_left, and
* the right side will not start with an value from B_right.
* (It can be easily seen from the example down below, just
* follow the steps of the merge algorithm.)
*
* Thus the desired median elements are somewhere in
* A_right or B_left. When computing the median we can get rid
* of the same amount of elements on the right as on the left side
* and the result will not change in case the elements on the left
* are smaller than the median, meanwhile elements on the right
* are greater. So we can do here: A_left and B_right can be
* thrown away leaving us with just A_right and B_left -
* now we have the same problem but of half of the size.
*
* Example:
* a = [ 1, 2, 3, 4, 8 ]
* b = [ 0, 3, 4, 5, 6 ]
* Merged: [ 0, 1*, 2*, 3, 3* | 4, 4*, 5, 6, 8* ]
* (elements from the first array are marked with asterisks)
*
* - mid1 > mid2 case is handled similarly. */
static double medianTwoArrays(double[] a, double[] b) {
if (a.length != b.length) {
"Expected: len(a) == len(b)."
+ "Got: len(a) = %d, len(b) = %d",
a.length, b.length
));
}
final int n = a.length;
int lo1 = 0, hi1 = n; // left subarray
int lo2 = 0, hi2 = n; // right subarray
while (hi1 - lo1 > 2) {
double mid1 = a[(lo1 + hi1) >>> 1];
double mid2 = b[(lo2 + hi2) >>> 1];
if (mid1 > mid2) {
double[] arraySwap = a;
a = b;
b = arraySwap;
int swap = lo1;
lo1 = lo2;
lo2 = swap;
swap = hi1;
hi1 = hi2;
hi2 = swap;
} else if (mid1 == mid2) {
return mid1;
}
lo1 = (lo1 + hi1) >>> 1;
hi2 = (lo2 + hi2 + 1) >>> 1;
}
if (hi1 - lo1 == 1) {
return (a[lo1] + b[lo2]) / 2;
} else {
assert hi1 - lo1 == 2;
// [a0, a1] [b0, b1] case
// possible merged arrays:
// a0 < b0
// [a0, a1, b0, b1] mid = avg(a1, b0) -- a1 < b0 < b1
// [a0, b0, a1, b1] mid = avg(a1, b0) -- a1 < b1
// [a0, b0, b1, a1] mid = avg(b1, b0) -- a1 > b1
//
// a0 > b0
// [b0, a0, b1, a1] mid = avg(a0, b1) -- a1 > b1
// [b0, a0, a1, b1] mid = avg(a0, a1) -- a1 < b1
// [b0, b1, a0, a1] mid = avg(a0, b1) -- a1 > a0 > b1
return (max(a[lo1], b[lo2])
+ min(a[lo1 + 1], b[lo2 + 1])) / 2;
}
}
public static void main
(String[] args
) { double[] a = { 1, 12, 15, 26, 38 };
double[] b = { 2, 13, 17, 30, 45 };
System.
out.
println(medianTwoArrays
(a, b
)); System.
out.
println(medianTwoArraysLinear
(a, b
)); }
}
aW1wb3J0IHN0YXRpYyBqYXZhLmxhbmcuTWF0aC5tYXg7CmltcG9ydCBzdGF0aWMgamF2YS5sYW5nLk1hdGgubWluOwoKY2xhc3MgS3RoTGFyZ2VzdFR3b0FycmF5cyB7CiAgICAvKioKICAgICAqIEdpdmVuIHR3byBzb3J0ZWQgYXJyYXlzIG9mIGVxdWFsIHNpemVzLCBmaW5kcyB0aGUgbWVkaWFuIG9mIHRoZQogICAgICogYXJyYXkgdGhhdCBjb21lcyBvdXQgYWZ0ZXIgYGFgIGFuZCBgYmAgYmVpbmcgbWVyZ2VkLiBSdW5zIGluCiAgICAgKiBsaW5lYXIgdGltZSBhbmQgZG9lcyBub3QgcmVxdWlyZSBhbnkgZXh0cmEgc3BhY2UuCiAgICAgKgogICAgICogVGhlIGFsZ29yaXRobSBpcyBzaW1pbGFyIHRvIHRoZSBhcnJheXMgbWVyZ2luZywgYnV0IGl0CiAgICAgKiBkb2VzIG5vdCBzYXZlIHRoZSBtZXJnZWQgYXJyYXksIGl0IGp1c3QgaXRlcmF0ZXMgdGhyb3VnaCBib3RoCiAgICAgKiBvZiB0aGVtIGJ5IG4rMSBpdGVtcyAodGh1cyBzdG9wcGluZyBpbiB0aGUgbWlkZGxlIG9mIGFuIGltYWdpbmFyeQogICAgICogbWVyZ2VkIGFycmF5KSBhbmQgbWVtb3JpemVzIHR3byBjb25zZWN1dGl2ZSBlbGVtZW50cy4gVGhlc2UKICAgICAqIGFyZSB0aGUgdHdvIGVsZW1lbnRzIGxheWluZyBleGFjdGx5IGluIHRoZSBtaWRkbGUgb2YgbWVyZ2VkIGFycmF5LgogICAgICoKICAgICAqIChTaW5jZSB0aGUgbGVuZ3RoIG9mIHRoZSBtZXJnZWQgYXJyYXkgaXMgZXZlbiwgaXRzIG1lZGlhbgogICAgICogaXMgYW4gYXZlcmFnZSB2YWx1ZSBvZiB0d28gZWxlbWVudHMgaW4gdGhlIG1pZGRsZS4pCiAgICAgKgogICAgICogQHBhcmFtIGEgYSBzb3J0ZWQgYXJyYXkKICAgICAqIEBwYXJhbSBiIGEgc29ydGVkIGFycmF5CiAgICAgKi8KICAgIHN0YXRpYyBkb3VibGUgbWVkaWFuVHdvQXJyYXlzTGluZWFyKGRvdWJsZVtdIGEsIGRvdWJsZVtdIGIpIHsKICAgICAgICBpZiAoYS5sZW5ndGggIT0gYi5sZW5ndGgpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbihTdHJpbmcuZm9ybWF0KAogICAgICAgICAgICAgICAgIkV4cGVjdGVkOiBsZW4oYSkgPT0gbGVuKGIpLiIKICAgICAgICAgICAgICAgICsgIiBHb3Q6IGxlbihhKSA9ICVkLCBsZW4oYikgPSAlZCIsCiAgICAgICAgICAgICAgICBhLmxlbmd0aCwgYi5sZW5ndGgKICAgICAgICAgICAgKSk7CiAgICAgICAgfQogICAgICAgIAogICAgICAgIGZpbmFsIGludCBuID0gYS5sZW5ndGg7CiAgICAgICAgaW50IGkgPSAwLCBqID0gMDsKICAgICAgICAvLyB0d28gY29uc2VjdXRpdmUgZWxlbWVudHMgb2YgdGhlIG1lcmdlZCBhcnJheQogICAgICAgIGRvdWJsZSBtaWQxID0gRG91YmxlLk5hTiwgbWlkMiA9IERvdWJsZS5OYU47CiAgICAgICAgZm9yIChpbnQgayA9IDA7IGsgPCBuICsgMTsgaysrKSB7CiAgICAgICAgICAgIC8vIGhlcmUgd2UgYWxzbyBoYW5kbGUgYSBzcGVjaWFsIGNhc2Ugd2hlbiBldmVyeSBlbGVtZW50CiAgICAgICAgICAgIC8vIG9mIHRoZSBmaXJzdCBhcnJheSBpcyBzbWFsbGVyIHRoYW4gdGhlIHNtYWxsZXN0IGVsZW1lbnQKICAgICAgICAgICAgLy8gb2YgdGhlIHNlY29uZCBhcnJheSAoYW5kIHZpY2UgdmVyc2EpCiAgICAgICAgICAgIGlmIChqID09IG4gfHwgaSA8IG4gJiYgYVtpXSA8IGJbal0pIHsKICAgICAgICAgICAgICAgIC8vIHB1dCB0aGUgcHJldmlvdXMgdmFsdWUgaW50byB0aGUgYnVmZmVyCiAgICAgICAgICAgICAgICBtaWQxID0gbWlkMjsKICAgICAgICAgICAgICAgIG1pZDIgPSBhW2ldOwogICAgICAgICAgICAgICAgaSsrOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgbWlkMSA9IG1pZDI7CiAgICAgICAgICAgICAgICBtaWQyID0gYltqXTsKICAgICAgICAgICAgICAgIGorKzsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gKG1pZDEgKyBtaWQyKSAvIDI7CiAgICB9CiAgICAKICAgIC8qKgogICAgICogQSBsb2dhcml0aG1pYy10aW1lIGFsZ29yaXRobSB0aGF0IHNvbHZlcyB0aGUgc2FtZSBwcm9ibGVtLgogICAgICogVGhlIGJhc2ljIGlkZWEgaXMgdG8gY29tcHV0ZSB0aGUgbWVkaWFucyBvZiBib3RoIG9mIHRoZQogICAgICogYXJyYXlzICh3ZWxsLCB0aGVzZSBhcmUgbm90IGV4YWN0bHkgIm1lZGlhbnMiLCBpbiBjYXNlIHRoZQogICAgICogYXJyYXkgbGVuZ3RoIGlzIGV2ZW4sIG1pZCA9IEFbbiAvIDJdLCBub3QgdGhlIGF2ZXJhZ2UgdmFsdWUpOgogICAgICogICAgIEEgPSBbYTEsIGEyLCAuLi4sIG1pZDEsIC4uLiwgYW5dIAogICAgICogICAgIEIgPSBbYjEsIGIyLCAuLi4sIG1pZDIsIC4uLiwgYm5dCiAgICAgKiBhbmQgYWZ0ZXIgdGhhdCB0aGVyZSBhcmUgdGhyZWUgY2FzZXMgdG8gY29uc2lkZXI6CiAgICAgKgogICAgICogIC0gbWlkMSA9PSBtaWQyLCB3aGljaCBtZWFucyAoZ2l2ZW4gbGVuKEEpID09IGxlbihCKSkgdGhhdAogICAgICogICAgaW4gZXZlcnkgYXJyYXkgdGhlcmUgYXJlIG4vMiBlbGVtZXRzIG9uIHRoZSBsZWZ0IHNpZGUKICAgICAqICAgIGZyb20gdGhlIG1pZCwgc28gaW4gdGhlIG1lcmdlZCBhcnJheSBtaWQxIGFuZCBtaWQyIHdvdWxkCiAgICAgKiAgICBiZSBvbiBuLzIgKyBuLzIgPSBuIGFuZCBuKzEgcG9zaXRpb25zICh0aHVzIG1pZDEgaXMgdGhlCiAgICAgKiAgICBtZWRpYW4gb2YgdGhlIG1lcmdlZCBhcnJheSkKICAgICAqCiAgICAgKiAgLSBtaWQxICZsdDsgbWlkMiBtZWFucyB0aGF0IHRoZSBncmVhdGVzdCBlbGVtZW50IG9mIHRoZSBsZWZ0CiAgICAgKiAgICBzaWRlIG9mIHRoZSBhcnJheSBBIChBX2xlZnQpIGlzIGF0IG1vc3QgYXMgbGFyZ2UgYXMgdGhlCiAgICAgKiAgICBncmVhdGVzdCBlbGVtZW50IG9mIEJfbGVmdC4gQW5kIHNpbWlsYXJseSB0aGUgc21hbGxlc3QKICAgICAqICAgIGVsZW1lbnQgb2YgQl9yaWdodCBpcyBhdCBsZWFzdCBhcyBsYXJnZSBhcyB0aGUgc21hbGxlc3QKICAgICAqICAgIGVsZW1lbnQgb2YgQV9yaWdodC4KICAgICAqCiAgICAgKiAgICBUaGlzIG1lYW5zIHRoYXQgdGhlIGxlZnQgc2lkZSBvZiB0aGUgaW1hZ2luYXJ5IG1lcmdlZCBhcnJheQogICAgICogICAgZm9yIHN1cmUgd291bGQgbm90IGVuZCB3aXRoIGFuIGVsZW1lbnQgZnJvbSBBX2xlZnQsIGFuZAogICAgICogICAgdGhlIHJpZ2h0IHNpZGUgd2lsbCBub3Qgc3RhcnQgd2l0aCBhbiB2YWx1ZSBmcm9tIEJfcmlnaHQuCiAgICAgKiAgICAoSXQgY2FuIGJlIGVhc2lseSBzZWVuIGZyb20gdGhlIGV4YW1wbGUgZG93biBiZWxvdywganVzdAogICAgICogICAgZm9sbG93IHRoZSBzdGVwcyBvZiB0aGUgbWVyZ2UgYWxnb3JpdGhtLikKICAgICAqCiAgICAgKiAgICBUaHVzIHRoZSBkZXNpcmVkIG1lZGlhbiBlbGVtZW50cyBhcmUgc29tZXdoZXJlIGluCiAgICAgKiAgICBBX3JpZ2h0IG9yIEJfbGVmdC4gV2hlbiBjb21wdXRpbmcgdGhlIG1lZGlhbiB3ZSBjYW4gZ2V0IHJpZAogICAgICogICAgb2YgdGhlIHNhbWUgYW1vdW50IG9mIGVsZW1lbnRzIG9uIHRoZSByaWdodCBhcyBvbiB0aGUgbGVmdCBzaWRlCiAgICAgKiAgICBhbmQgdGhlIHJlc3VsdCB3aWxsIG5vdCBjaGFuZ2UgaW4gY2FzZSB0aGUgZWxlbWVudHMgb24gdGhlIGxlZnQKICAgICAqICAgIGFyZSBzbWFsbGVyIHRoYW4gdGhlIG1lZGlhbiwgbWVhbndoaWxlIGVsZW1lbnRzIG9uIHRoZSByaWdodAogICAgICogICAgYXJlIGdyZWF0ZXIuIFNvIHdlIGNhbiBkbyBoZXJlOiBBX2xlZnQgYW5kIEJfcmlnaHQgY2FuIGJlCiAgICAgKiAgICB0aHJvd24gYXdheSBsZWF2aW5nIHVzIHdpdGgganVzdCBBX3JpZ2h0IGFuZCBCX2xlZnQgLQogICAgICogICAgbm93IHdlIGhhdmUgdGhlIHNhbWUgcHJvYmxlbSBidXQgb2YgaGFsZiBvZiB0aGUgc2l6ZS4KICAgICAqCiAgICAgKiAgICBFeGFtcGxlOgogICAgICogICAgYSA9IFsgMSwgMiwgMywgNCwgOCBdCiAgICAgKiAgICBiID0gWyAwLCAzLCA0LCA1LCA2IF0KICAgICAqICAgIE1lcmdlZDogWyAwLCAxKiwgMiosIDMsIDMqIHwgNCwgNCosIDUsIDYsIDgqIF0KICAgICAqICAgIChlbGVtZW50cyBmcm9tIHRoZSBmaXJzdCBhcnJheSBhcmUgbWFya2VkIHdpdGggYXN0ZXJpc2tzKQogICAgICoKICAgICAqICAtIG1pZDEgJmd0OyBtaWQyIGNhc2UgaXMgaGFuZGxlZCBzaW1pbGFybHkuICAqLyAKICAgIHN0YXRpYyBkb3VibGUgbWVkaWFuVHdvQXJyYXlzKGRvdWJsZVtdIGEsIGRvdWJsZVtdIGIpIHsKICAgICAgICBpZiAoYS5sZW5ndGggIT0gYi5sZW5ndGgpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbihTdHJpbmcuZm9ybWF0KAogICAgICAgICAgICAgICAgIkV4cGVjdGVkOiBsZW4oYSkgPT0gbGVuKGIpLiIKICAgICAgICAgICAgICAgICsgIkdvdDogbGVuKGEpID0gJWQsIGxlbihiKSA9ICVkIiwKICAgICAgICAgICAgICAgIGEubGVuZ3RoLCBiLmxlbmd0aAogICAgICAgICAgICApKTsKICAgICAgICB9IAogICAgICAgIGZpbmFsIGludCBuID0gYS5sZW5ndGg7CiAgICAgICAgaW50IGxvMSA9IDAsIGhpMSA9IG47IC8vIGxlZnQgc3ViYXJyYXkKICAgICAgICBpbnQgbG8yID0gMCwgaGkyID0gbjsgLy8gcmlnaHQgc3ViYXJyYXkKCiAgICAgICAgd2hpbGUgKGhpMSAtIGxvMSA+IDIpIHsKICAgICAgICAgICAgZG91YmxlIG1pZDEgPSBhWyhsbzEgKyBoaTEpID4+PiAxXTsKICAgICAgICAgICAgZG91YmxlIG1pZDIgPSBiWyhsbzIgKyBoaTIpID4+PiAxXTsKCiAgICAgICAgICAgIGlmIChtaWQxID4gbWlkMikgewogICAgICAgICAgICAgICAgZG91YmxlW10gYXJyYXlTd2FwID0gYTsKICAgICAgICAgICAgICAgIGEgPSBiOwogICAgICAgICAgICAgICAgYiA9IGFycmF5U3dhcDsKCiAgICAgICAgICAgICAgICBpbnQgc3dhcCA9IGxvMTsKICAgICAgICAgICAgICAgIGxvMSA9IGxvMjsKICAgICAgICAgICAgICAgIGxvMiA9IHN3YXA7CgogICAgICAgICAgICAgICAgc3dhcCA9IGhpMTsKICAgICAgICAgICAgICAgIGhpMSA9IGhpMjsKICAgICAgICAgICAgICAgIGhpMiA9IHN3YXA7CiAgICAgICAgICAgIH0gZWxzZSBpZiAobWlkMSA9PSBtaWQyKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gbWlkMTsKICAgICAgICAgICAgfQogICAgICAgICAgICBsbzEgPSAobG8xICsgaGkxKSA+Pj4gMTsKICAgICAgICAgICAgaGkyID0gKGxvMiArIGhpMiArIDEpID4+PiAxOwogICAgICAgIH0KCiAgICAgICAgaWYgKGhpMSAtIGxvMSA9PSAxKSB7CiAgICAgICAgICAgIHJldHVybiAoYVtsbzFdICsgYltsbzJdKSAvIDI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgYXNzZXJ0IGhpMSAtIGxvMSA9PSAyOwogICAgICAgICAgICAvLyBbYTAsIGExXSBbYjAsIGIxXSBjYXNlCiAgICAgICAgICAgIC8vIHBvc3NpYmxlIG1lcmdlZCBhcnJheXM6CiAgICAgICAgICAgIC8vICAgYTAgPCBiMAogICAgICAgICAgICAvLyAgIFthMCwgYTEsIGIwLCBiMV0gbWlkID0gYXZnKGExLCBiMCkgLS0gYTEgPCBiMCA8IGIxCiAgICAgICAgICAgIC8vICAgW2EwLCBiMCwgYTEsIGIxXSBtaWQgPSBhdmcoYTEsIGIwKSAtLSBhMSA8IGIxCiAgICAgICAgICAgIC8vICAgW2EwLCBiMCwgYjEsIGExXSBtaWQgPSBhdmcoYjEsIGIwKSAtLSBhMSA+IGIxCiAgICAgICAgICAgIC8vICAgCiAgICAgICAgICAgIC8vICAgYTAgPiBiMAogICAgICAgICAgICAvLyAgIFtiMCwgYTAsIGIxLCBhMV0gbWlkID0gYXZnKGEwLCBiMSkgLS0gYTEgPiBiMQogICAgICAgICAgICAvLyAgIFtiMCwgYTAsIGExLCBiMV0gbWlkID0gYXZnKGEwLCBhMSkgLS0gYTEgPCBiMQogICAgICAgICAgICAvLyAgIFtiMCwgYjEsIGEwLCBhMV0gbWlkID0gYXZnKGEwLCBiMSkgLS0gYTEgPiBhMCA+IGIxCiAgICAgICAgICAgIHJldHVybiAobWF4KGFbbG8xXSwgYltsbzJdKQogICAgICAgICAgICAgICAgICAgICsgbWluKGFbbG8xICsgMV0sIGJbbG8yICsgMV0pKSAvIDI7CiAgICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgdm9pZCBtYWluKFN0cmluZ1tdIGFyZ3MpIHsKICAgICAgICBkb3VibGVbXSBhID0geyAxLCAxMiwgMTUsIDI2LCAzOCB9OwogICAgICAgIGRvdWJsZVtdIGIgPSB7IDIsIDEzLCAxNywgMzAsIDQ1IH07CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKG1lZGlhblR3b0FycmF5cyhhLCBiKSk7CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKG1lZGlhblR3b0FycmF5c0xpbmVhcihhLCBiKSk7CiAgICB9Cn0=