There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
解题思路:对于a,b数组(保证a长度小于b长度),要取第k个数
我们先假设从a,b各取k/2个
如果a长度大于k/2(则b也一定大于),那么比较a[k/2-1]和b[k/2-1]
假设前者大于后者,那么a的前k/2个元素,必定包含在最小的k个元素里面(只两个数组一起算,最小的k个)。剩下k/2可能在a的k/2个元素以后取,也可能在b的前k/2个元素里面取,但是都没有关系,反正a的前k/2是一定包含在最小的k个元素里面的。那么我可以去掉a的前k/2个元素,接着求a(去掉前k/2以后),b数组的第k-k/2小的元素(递归)
如果后者大于前者,和上面一样道理,可以去掉b的前k/2个元素,接着求b(去掉前k/2以后),a数组的第k-k/2小的元素(递归)
如果两者相等,那么a[k/2-1]和b[k/2-1]就是我们要找的第k个元素,直接返回
上面的描述考虑了a长度大于k/2的情况,如果a长度小于k/2呢
那么我们就去掉a的剩余长度,然后在b里面,求第k-a.length个元素的就可以了。因为和上面说的一样,a剩余的元素,必然包含在最小的前k个元素里面,我们去掉这些元素以后,就可以b里面直接求k-a.length个元素,就是所求。
public class Solution {
/**
* @param a
* @param b
* @param start_a a数组起始位置
* @param start_b b数组起始位置
* @param k 要找第k个数
* @return
*/
double findKth(int[] a,int[] b,int start_a,int start_b,int k){
if(a.length-start_a>b.length-start_b){//保证前一个数组长度,小于后一个数组
return findKth(b, a, start_b, start_a, k);
}
if(a.length-start_a==0){//如果a数组已经数尽,直接返回b数组中的第k个值,对应index为k-1
return b[k-1];
}
if(k==1){//如果要找第一个数,那么返回两者较小的
return Math.min(a[start_a], b[start_b]);
}
int pa = Math.min(k/2, a.length-start_a);//比较a数组剩余的长度和k/2,取较小的
int pb = k - pa;//剩余的让b来处理
/*
* 如果从当前start_a开始的第k/2个数(也可能是a的最后一个数,因为a的剩余长度不够k/2)
* 小于从当前start_b开始的第k/2个数(也可能是start_b开始的第a剩余长度个数)
* 则,去掉a这一部分(可能是k/2,也可能是a的剩余部分)
*/
if (a[start_a+pa-1] < b[start_b+pb-1])
return findKth(a, b, start_a+pa, start_b, k - pa);
else if (a[start_a+pa-1] > b[start_b+pb-1])//否则去掉b一部分(可能是k/2,也可能是a的剩余部分)
return findKth(a, b, start_a, start_b+pb, k - pb);
else//否则a,b都可以第k/2相等,则这个数为所求,返回即可
return a[start_a+pa-1];
}
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int total = nums1.length + nums2.length;
if((total&1)==1)
return findKth(nums1, nums2, 0, 0, total/2+1);
else
System.out.println("a");
return (findKth(nums1, nums2, 0, 0, total/2)
+ findKth(nums1, nums2, 0, 0, total/2+1))/2;
}
}