https://leetcode-cn.com/problems/median-of-two-sorted-arrays/
思路:这个复杂度限定还是挺有意思的。假设 g e t k t h ( k ) getkth(k) getkth(k)可以求出数组 a a a和数组 b b b后并之后的第 k k k个数,设数组 a 、 b a、b a、b的长度分别为 n 1 、 n 2 n_1、n_2 n1、n2,设 k 1 = ( n 1 + n 2 + 1 ) / 2 , k 2 = ( n 1 + n 2 + 2 ) / 2 k_1=(n_1+n_2+1)/2,k_2=(n_1+n_2+2)/2 k1=(n1+n2+1)/2,k2=(n1+n2+2)/2,那么数组 a 、 b a、b a、b的中位数就等于 ( g e t k t h ( k 1 ) + g e t k t h ( k 2 ) ) / 2.0 (getkth(k_1)+getkth(k_2))/2.0 (getkth(k1)+getkth(k2))/2.0。这个比较简单,大家举几个例子就能推出来。现在我们考虑怎么实现这个 g e t k t h getkth getkth函数。我们可以设 k k = k / 2 kk=k/2 kk=k/2,那么通过比较 a [ k k ] a[kk] a[kk]和 b [ k k ] b[kk] b[kk]的大小,就可以筛去一部分不合题意的数字。假设 a [ k k ] > = b [ k k ] a[kk]>=b[kk] a[kk]>=b[kk], a a a数组中 < = a [ k k ] <=a[kk] <=a[kk]的数共有 k k − 1 kk-1 kk−1个, b b b数组中 < = b [ k k ] <=b[kk] <=b[kk]的数共有 k k − 1 kk-1 kk−1个,就算 b [ k k ] > = a [ k k − 1 ] b[kk]>=a[kk-1] b[kk]>=a[kk−1],那么小于 b [ k k ] b[kk] b[kk]的数最多只有 2 ∗ k k − 2 2*kk-2 2∗kk−2个,也就是说 b [ k k ] b[kk] b[kk]最大也不过是第 k − 1 k-1 k−1大的数,由此我们可以看出 b [ 0 … k k ] b[0…kk] b[0…kk]均不是符合题意的解,因此可以把这部分数筛去,问题转换成求两个新数组的第 k − ( k k + 1 ) k-(kk+1) k−(kk+1)大的数。那么递归进行这个过程,就可以求得解。为了方便起见,我们在函数中新增 4 4 4个参数 b e g 1 , e n d 1 , b e g 2 , e n d 2 beg_1,end_1,beg_2,end_2 beg1,end1,beg2,end2用来限制 a 、 b a、b a、b的范围,这样可以使得筛去操作容易实现。递归的出口就是 b e g 1 = e n d 1 beg_1=end_1 beg1=end1或 b e g 2 = e n d 2 beg_2=end_2 beg2=end2或 k = 1 k=1 k=1。同时考虑到某个数组的实际个数可能小于 k k kk kk,在限定范围的时候需要注意。
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n1=nums1.size();
int n2=nums2.size();
int k1=(n1+n2+1)>>1;
int k2=(n1+n2+2)>>1;
return (getkth(nums1,0,n1,nums2,0,n2,k1)+getkth(nums1,0,n1,nums2,0,n2,k2))/2.0;
}
int getkth(vector<int>& nums1,int beg1,int end1,vector<int>& nums2,int beg2,int end2,int k){
int len1=end1-beg1;
int len2=end2-beg2;
if(len1==0)
return nums2[beg2+k-1];
if(len2==0)
return nums1[beg1+k-1];
if(k==1)
return min(nums1[beg1],nums2[beg2]);
int id1=beg1+min(len1,k>>1)-1;
int id2=beg2+min(len2,k>>1)-1;
if(nums1[id1]>=nums2[id2])
return getkth(nums1,beg1,end1,nums2,id2+1,end2,k-(id2-beg2+1));
else
return getkth(nums1,id1+1,end1,nums2,beg2,end2,k-(id1-beg1+1));
}
};