暴力解法:
将两个有序数组合并起来,然后取中位数。
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int l1 = nums1.length;
int l2 = nums2.length;
if (l1 == 0) {
return ((l2 % 2) == 0 ? ((nums2[l2 / 2] + nums2[l2 / 2 - 1]) / 2.0) : nums2[l2 / 2]);
}
if (l2 == 0) {
return ((l1 % 2) == 0 ? ((nums1[l1 / 2] + nums1[l1 / 2 - 1]) / 2.0) : nums1[l1 / 2]);
}
int nums[] = new int[l1 + l2];
int count = 0;
int i = 0;
int j = 0;
while (count != nums.length) {
if (i == l1) {
while (j != l2) {
nums[count++] = nums2[j++];
}
break;
}
if (j == l2) {
while (i != l1) {
nums[count++] = nums1[i++];
}
break;
}
if (nums1[i] < nums2[j]) {
nums[count++] = nums1[i++];
} else {
nums[count++] = nums2[j++];
}
}
if (count % 2 == 0) {
return (nums[count / 2 - 1] + nums[count / 2]) / 2.0;
} else {
return nums[count / 2];
}
}
同样因为数组长度已知,中位数下标已知,通过两个指针同时遍历两个数组也可获取中位数。
第K小:
要找中位数想法等同于查找第中位数K小的数(长度为偶数时还需求第K-1小的数并除2)
想法是将K分为两部分(对应有两个数组),将类似滑动窗口左边界的处理,首先将两数组左边界改为当前位置+(K/2)(注意此值可能下标越界,若越界则指向最后一个下标即可),若数组1的左边界<数组2的左边界,那么数组1左边界以左包括边界都不可能是第K小的数,那么就把数组1左边界右移一个位置,K也需要减去不可能的数;
重复该操作,直到①有数组遍历完,则结果为另一个数组当前下标加K-1②当K为1,结果为两个数组当前位置较小数。
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int l1 = nums1.length;
int l2 = nums2.length;
int whole = l1 + l2;
if (whole % 2 == 0) {
return ((getK(nums1, nums2, whole / 2 + 1) + getK(nums1, nums2, whole / 2)) / 2.0);
} else {
return (getK(nums1, nums2, whole / 2 + 1));
}
}
int getK(int[] nums1, int[] nums2, int k) {
int index1 = 0;
int index2 = 0;
while (true) {
if (index1 == nums1.length) {
return nums2[index2 + k - 1];
}
if (index2 == nums2.length) {
return nums1[index1 + k - 1];
}
if (k == 1) {
return Math.min(nums1[index1], nums2[index2]);
}
int half = k / 2;
int new1 = Math.min(nums1.length, index1 + half) - 1;
int new2 = Math.min(nums2.length, index2 + half) - 1;
if (nums1[new1] > nums2[new2]) {
k -= (new2 - index2 + 1);
index2 = new2 + 1;
} else {
k -= (new1 - index1 + 1);
index1 = new1 + 1;
}
}
}