== case1==:此时k/2都比数组的有效长度小
case2:数组长度小于k/2
case3:查找的只剩下一个数组
注意:偶数长度的情况,可能出现0.5的小数位数,注意使用乘的0.5自动转换为double类型
具体代码:
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int n = nums1.length;
int m = nums2.length;
//注意这个left和right对应的不是数组的有效序号,而是从1开始计数的具体位置
int left = (n + m + 1) / 2;
int right = (n + m + 2) / 2;
//将偶数和奇数的情况合并,如果是奇数,会求两次同样的 k(即left==right)
//注意这里乘的0.5这样可以转换为double(不要单纯的除以2,还是int)
return (getKth(nums1, 0, n - 1, nums2, 0, m - 1, left) + getKth(nums1, 0, n - 1, nums2, 0, m - 1, right))*0.5;
}
//每次更新出数组nums1和nums2有效索引,对应的剩余的查找数组个数k(采用二分法)
/**
start:即为有效查找的数组的开始序号
end:即为数组的尾部序号
k:即为剩余离中位数的距离的个数
note:注意数组小标与第几个数的区别,数组的序号需要相对于低基数减1
*/
private int getKth(int[] nums1, int start1, int end1, int[] nums2, int start2, int end2, int k) {
//求出对应的有效查找数组的长度
int len1 = end1 - start1 + 1;
int len2 = end2 - start2 + 1;
//让 len1 的长度小于 len2,这样就能保证如果有数组空了,一定是 len1 (避免了分类讨论时的重复操作)
if (len1 > len2){
//相当于利用对称的性质
return getKth(nums2, start2, end2, nums1, start1, end1, k);
}
if (len1 == 0){
//总是nums1先跳出循环(单独取出数组nums2的数)
return nums2[start2 + k - 1];//(个数转换为序号减1)
}
if (k == 1){
//此时需要判断最后一个数
return Math.min(nums1[start1], nums2[start2]);
}
//用于更新有效查找的数组的长度(2选1)
//找到两个数的带比较的两个数的有效索引的位置
int i = start1 + Math.min(len1, k / 2) - 1;
int j = start2 + Math.min(len2, k / 2) - 1;
if (nums1[i] > nums2[j]) {//更新小的数组nums2索引以及剩余离中位数的距离的个数
return getKth(nums1, start1, end1, nums2, j + 1, end2, k - Math.min(len2, k / 2));
}
else {//更新小的数组nums1索引以及剩余离中位数的距离的个数
return getKth(nums1, i + 1, end1, nums2, start2, end2, k - Math.min(len1, k / 2));
}
}
}