T4 寻找两个正序数组的中位数
链接: link
思路1: 暴力解法:直接将两个数组合并,得到中位数
class Solution {
public:
int MAXN=1e7;
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
//思路1: 暴力解法:直接将两个数组合并,得到中位数
double ans;
int n1=nums1.size(),n2=nums2.size();
if(!n1){
if(n2%2){
return nums2[n2/2];
}
else{
return (nums2[n2/2]+nums2[n2/2-1])/2.0;
}
}
if(!n2){
if(n1%2){
return nums1[n1/2];
}
else{
return (nums1[n1/2]+nums1[n1/2-1])/2.0;
}
}
int nums[n1+n2];
for(int i=0,j=0,k=0;i<n1 || j<n2;){
int temp1=(i<n1?nums1[i]:MAXN);
int temp2=(j<n2?nums2[j]:MAXN);
if(temp1<temp2){
nums[k++]=temp1;
i++;
}
else{
nums[k++]=temp2;
j++;
}
}
int n=n1+n2;
if(n%2){
return nums[n/2];
}
else{
return (nums[n/2]+nums[n/2-1])/2.0;
}
}
};
实际上此种思路不需要将两个数组完全合并,当k满足大于(n1+n2)/2即可中止,根据n的奇偶返回中位数即可,可以将复杂度降低一半左右。
思路2:不进行合并,直接利用两数组有序,进行中位数查找(减少空间复杂度,并利用二分查找降低时间复杂度)
大致思路:假定需要查询的为第k小数,则每次舍去k/2个数(更新k,k是不断除2,避免误解)。用a,b分别记录两个数组还未舍去的头部指针,每次比较nums1[a+k/2]和nums2[b+k/2],更新较小的数组的头部指针,直至k=1或某个数组遍历完。
需要注意的是,当总数为偶数时,中位数为两个数的平均值,
具体参考:(链接) link中的方法一,里面的图解还是挺清晰的
class Solution {
public:
int findkth(vector<int>& nums1, vector<int>& nums2, int k){
int m=nums1.size(),n=nums2.size();
int a=0, b=0;
while(1){
if(a==m){
return nums2[b+k-1];
}
if(b==n){
return nums1[a+k-1];
}
if(k==1){
return min(nums1[a],nums2[b]);
}
int index1=min(a+k/2-1,m-1);
int index2=min(b+k/2-1,n-1);
if(nums1[index1]<nums2[index2]){
k-=index1-a+1;
a=index1+1;
}
else{
k-=index2-b+1;
b=index2+1;
}
}
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
//思路2: 二分查找
int k=nums1.size()+nums2.size();
if(k%2){ //奇数
return findkth(nums1,nums2,k/2+1)*1.0;
}
else{
return (findkth(nums1,nums2,k/2)+findkth(nums1,nums2,k/2+1))/2.0;
}
}
};