leetcode #4寻找两个正序数组的中位数
O(m+n)的思路大家都会, 合并两个数组再找出中位数即可
题目的进阶要求是时间复杂度为O(log(m+n), 思路是使用二分查找, 将寻找中位数转换为寻找第k小的元素, 详细见代码注释
public class Test{
static void print(String x){
System.out.println(x);
}
static void print(int x){
System.out.println(x);
}
static void print(double x){
System.out.println(x);
}
public int getKelement(int[] nums1, int[] nums2, int k){
/**
* 查询两个从小到大有序数组种的第k小元素
* 0边界情况
* 0.1 取index = k / 2 - 1,若nums1[index]或nums2[index]数组越界,
* 则选取对应的数组最大值来与另一个数组的index元素进行比较, 此时k的更新要以排除的元素个数减去
* 0.2 k = 1, 结果为nums1与nums2剩下元素中最起始位置的最小值,即min(nums1[0], nums2[0])
* 0.3 nums1为空, 返回为nums2[k - 1]
* 0.4 nums2为空, 返回为nums1[k - 1]
* 1.比较nums1[index]与nums2[index]
* 2.若nums1[index] <= nums2[index], 则排除nums1[0, 1, ..., index], 因为至多有 2*index <= k - 2个元素比nums1[index]小,
* nums1[index]至多是第k-1小而不是第k小, 所以可以排除nums1[index]以及比它小的nums1[0, 1, ... index - 1];
* 3.否则若nums1[index] > nums2[index], 则排除nums2[0, 1, ..., index];
* 4.之后 k = k - 排除的元素个数(正常情况为 k/2), 回到0, 继续再剩下的元素里寻找第k小元素;
*/
int length1 = nums1.length, length2 = nums2.length;
// index1, index2分别表示nums1中和nums2中已经排除的元素个数
int index1 = 0, index2 = 0;
while(true){
//边界
if(index1 >= length1){
return nums2[index2 + k - 1];
}
if(index2 >= length2){
return nums1[index1 + k - 1];
}
if(k == 1){
return Math.min(nums1[index1], nums2[index2]);
}
//正常
int half = k / 2;
int a = Math.min(index1 + half, length1);
int b = Math.min(index2 + half, length2);
if(nums1[a - 1] <= nums2[b - 1]){
k -= a - index1;
index1 = a;
} else{
k -= b- index2;
index2 = b;
}
}
}
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int n1 = nums1.length, n2 = nums2.length;
int tot = n1 + n2;
if(tot % 2 == 1)
return 1.0 * getKelement(nums1, nums2, (tot + 1)/ 2);
else
return 1.0 * (getKelement(nums1, nums2, tot / 2) + getKelement(nums1, nums2, tot / 2 + 1))/ 2;
}
public static void main(String[] args) {
Test test = new Test();
print(test.findMedianSortedArrays(new int[]{1, 2}, new int[]{3}));
}
}