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)).
本来以为是道挺简单的题,只是求两个数组的中值,大不了合成一个数组逐次比较就行。这个题主要就是复杂度卡住了,一个数组的话二分查找就行,两个数组要在O(log (m+n))时间内完成,则是比较麻烦的事。
经过思考,只能用递归来做。转化为求第k个值的问题,k=(m+n)/2。把k前面比中值小的值筛掉,则可得到中值。nums1中设一个值p1,nums2中设一个值p2,来确定两个数组中需要筛掉的数的位置,则p1+p2=k-1。如果nums1中第p1个数大于nums2中第p2个数,说明前p2个数都还不到中值的位置,则将nums2中前p2个数都筛掉。同理,对p1也一样。直到逼近k值。
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m=nums1.size();
int n=nums2.size();
if((m+n)%2==0){
return (findk(nums1,nums2,m,n,0,0,(m+n)/2)+findk(nums1,nums2,m,n,0,0,(m+n)/2+1))/2;
}
else{
return findk(nums1,nums2,m,n,0,0,(m+n)/2+1);
}
}
double findk(vector<int>& nums1, vector<int>& nums2,int m, int n, int s1, int s2, int k){
if(m>n){ //注意这里必须让数组的长短与p1和p2的定义对应
return findk(nums2,nums1,n,m,s2,s1,k);
}
if(m==0){
return nums2[s2+k-1];
}
if(k==1){
return min(nums1[s1],nums2[s2]);
}
//因为第一个比较取的是较短数组的队尾元素,因此要满足m<=k/2,否则可能出现另外一个数组越界的问题。
int p1=min(k/2,m);
int p2=k-p1;
if(nums1[s1+p1-1]>nums2[s2+p2-1]){
return findk(nums1,nums2,m,n-p2,s1,s2+p2,k-p2);
}
else if(nums1[s1+p1-1]<nums2[s2+p2-1]){
return findk(nums1,nums2,m-p1,n,s1+p1,s2,k-p1);
}
else{
return nums2[s2+p2-1];
}
}
};