|
|
package class12;
|
|
|
|
|
|
// 本题测试链接 : https://leetcode.com/problems/median-of-two-sorted-arrays/
|
|
|
public class Code03_FindKthMinNumber {
|
|
|
|
|
|
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
|
|
|
int size = nums1.length + nums2.length;
|
|
|
boolean even = (size & 1) == 0;
|
|
|
if (nums1.length != 0 && nums2.length != 0) {
|
|
|
if (even) {
|
|
|
return (double) (findKthNum(nums1, nums2, size / 2) + findKthNum(nums1, nums2, size / 2 + 1)) / 2D;
|
|
|
} else {
|
|
|
return findKthNum(nums1, nums2, size / 2 + 1);
|
|
|
}
|
|
|
} else if (nums1.length != 0) {
|
|
|
if (even) {
|
|
|
return (double) (nums1[(size - 1) / 2] + nums1[size / 2]) / 2;
|
|
|
} else {
|
|
|
return nums1[size / 2];
|
|
|
}
|
|
|
} else if (nums2.length != 0) {
|
|
|
if (even) {
|
|
|
return (double) (nums2[(size - 1) / 2] + nums2[size / 2]) / 2;
|
|
|
} else {
|
|
|
return nums2[size / 2];
|
|
|
}
|
|
|
} else {
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 进阶问题 : 在两个都有序的数组中,找整体第K小的数
|
|
|
// 可以做到O(log(Min(M,N)))
|
|
|
public static int findKthNum(int[] arr1, int[] arr2, int kth) {
|
|
|
int[] longs = arr1.length >= arr2.length ? arr1 : arr2;
|
|
|
int[] shorts = arr1.length < arr2.length ? arr1 : arr2;
|
|
|
int l = longs.length;
|
|
|
int s = shorts.length;
|
|
|
if (kth <= s) { // 1)
|
|
|
return getUpMedian(shorts, 0, kth - 1, longs, 0, kth - 1);
|
|
|
}
|
|
|
if (kth > l) { // 3)
|
|
|
if (shorts[kth - l - 1] >= longs[l - 1]) {
|
|
|
return shorts[kth - l - 1];
|
|
|
}
|
|
|
if (longs[kth - s - 1] >= shorts[s - 1]) {
|
|
|
return longs[kth - s - 1];
|
|
|
}
|
|
|
return getUpMedian(shorts, kth - l, s - 1, longs, kth - s, l - 1);
|
|
|
}
|
|
|
// 2) s < k <= l
|
|
|
if (longs[kth - s - 1] >= shorts[s - 1]) {
|
|
|
return longs[kth - s - 1];
|
|
|
}
|
|
|
return getUpMedian(shorts, 0, s - 1, longs, kth - s, kth - 1);
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// A[s1...e1]
|
|
|
// B[s2...e2]
|
|
|
// 一定等长!
|
|
|
// 返回整体的,上中位数!8(4) 10(5) 12(6)
|
|
|
public static int getUpMedian(int[] A, int s1, int e1, int[] B, int s2, int e2) {
|
|
|
int mid1 = 0;
|
|
|
int mid2 = 0;
|
|
|
while (s1 < e1) {
|
|
|
// mid1 = s1 + (e1 - s1) >> 1
|
|
|
mid1 = (s1 + e1) / 2;
|
|
|
mid2 = (s2 + e2) / 2;
|
|
|
if (A[mid1] == B[mid2]) {
|
|
|
return A[mid1];
|
|
|
}
|
|
|
// 两个中点一定不等!
|
|
|
if (((e1 - s1 + 1) & 1) == 1) { // 奇数长度
|
|
|
if (A[mid1] > B[mid2]) {
|
|
|
if (B[mid2] >= A[mid1 - 1]) {
|
|
|
return B[mid2];
|
|
|
}
|
|
|
e1 = mid1 - 1;
|
|
|
s2 = mid2 + 1;
|
|
|
} else { // A[mid1] < B[mid2]
|
|
|
if (A[mid1] >= B[mid2 - 1]) {
|
|
|
return A[mid1];
|
|
|
}
|
|
|
e2 = mid2 - 1;
|
|
|
s1 = mid1 + 1;
|
|
|
}
|
|
|
} else { // 偶数长度
|
|
|
if (A[mid1] > B[mid2]) {
|
|
|
e1 = mid1;
|
|
|
s2 = mid2 + 1;
|
|
|
} else {
|
|
|
e2 = mid2;
|
|
|
s1 = mid1 + 1;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return Math.min(A[s1], B[s2]);
|
|
|
}
|
|
|
|
|
|
}
|