等价于有序数组第K小
首先我们可以不断分割得到这个
k
k
k。
首先两个数组都分配
k
2
\frac{k}{2}
2k,如果第
k
2
\frac{k}{2}
2k个数,第一个数组小于第二个数组,那么第一个数组的
k
2
\frac{k}{2}
2k个数一定不是答案。
问题可以变成一个子问题,上一个数组从
k
2
+
1
\frac{k}{2}+1
2k+1开始。
相当于我们每次要去掉
k
/
2
k/2
k/2个不可能的元素。
如果有某个数组到底了,没有
k
/
2
k/2
k/2个元素了,那么肯定是从另一个数组扣除。
为什么呢?
我们考虑如果答案在上面,下面至少要有
>
k
/
2
>k/2
>k/2个去掉。
如果答案在下面,也要去掉至少
k
>
2
k>2
k>2个。
因为上面是
<
k
/
2
<k/2
<k/2的,所以下面无论如何第
k
k
k个也比
k
/
2
k/2
k/2多。
最后递归得到结果。
class Solution {
public:
int findK(vector<int>& nums1,int i,vector<int>& nums2,int j,int k){
if(i >= nums1.size())return nums2[j+k-1];
if(j >= nums2.size())return nums1[i+k-1];//数组为空
if(k == 1)return min(nums1[i],nums2[j]);//结束条件
int midl = i+k/2-1 < nums1.size() ? nums1[i+k/2-1] : 0x3f3f3f3f;
int midr = j+k/2-1 < nums2.size() ? nums2[j+k/2-1] : 0x3f3f3f3f;
if(midl <= midr)return findK(nums1,i+k/2,nums2,j,k-k/2);//如果前者小,那肯定不要前者的一半
else return findK(nums1,i,nums2,j+k/2,k-k/2);//如果后者小,肯定不要后者
}//算法核心在于二分区间,对于k然后不断缩小范围
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size(),m = nums2.size();
int l = findK(nums1,0,nums2,0,(n+m+1)/2);
int r = findK(nums1,0,nums2,0,(n+m+2)/2);
return (l + r) / 2.0;
}
};
非递归
class Solution {
public:
int findK(vector<int>& nums1,vector<int>& nums2,int k){
int i = 0,j = 0;
while(true){
if(i >= nums1.size())return nums2[j+k-1];
if(j >= nums2.size())return nums1[i+k-1];//数组为空
if(k == 1)return min(nums1[i],nums2[j]);//结束条件
int midl = i+k/2-1 < nums1.size() ? nums1[i+k/2-1] : 0x3f3f3f3f;
int midr = j+k/2-1 < nums2.size() ? nums2[j+k/2-1] : 0x3f3f3f3f;
if(midl <= midr)i += k/2;
else j += k/2;
k -= k/2;
}
}//算法核心在于二分区间,对于k然后不断缩小范围
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size(),m = nums2.size();
int l = findK(nums1,nums2,(n+m+1)/2);
int r = findK(nums1,nums2,(n+m+2)/2);
return (l + r) / 2.0;
}
};