标签:kth -o amp 中位数 第一个 直接 ndk return code
给定两个大小为 m 和 n 的正序(从小到大)数组?nums1 和?nums2。
请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为?O(log(m + n))。
你可以假设?nums1?和?nums2?不会同时为空。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
寻找数组中的中位数,即转化为寻找有序数组的第k小数问题(第k小的数即为中位数)
题目要求时间复杂度o(log(m+n))显然采用二分法,此题采用是折半删除找第k小数
问题:为什么可以直接删除第一个数组中的前k/2个数呢?
我们要寻找的是当前两个有序数组中的第k小的数,显然通过比较可以判断出剔除的k/2个数一定在第k小数的左边 可以直接剔除
证明:
设两个数组总元素个数为n
因为数组为有序递增数组,要证明所剔除的数都在第k小数左边,只需证明剔除的数中的最大数在第k小数的左边,即证明在该数右边的元素个数大于等于(n-k+1)
因为nums1[k/2-1]<nums2[k/2-1]时,两个数组中至少有n-(k/2)2+1个数大于等于nums1[k/2-1]
又因为k>=(k/2)2
所以n-(k/2)*2+1>=n-k+1
所以在nums1[k/2-1]右边的元素个数大于等于(n-k+1)
所以我们是可以直接剔除那些数的
不断进行折半剔除,直到k=1时,即中位数是当前数组剩余数中的最小数时,直接比较两个数组中当前的第一个数(即最小数)取较小的数即为中位数
代码如下
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n=nums1.size(),m=nums2.size();
int k1=(n+m+1)/2,k2=(n+m+2)/2;//当n+m为奇数时k1=k2;
return (findKth(nums1,0,n-1,nums2,0,m-1,k1)+findKth(nums1,0,n-1,nums2,0,m-1,k2))/2.0;//当n+m为奇数时即取到的同一个数,n+m为偶数即两个数取平均
}
int findKth(vector<int>&nums1,int le1,int ri1,vector<int>&nums2,int le2,int ri2,int k){
int length1=ri1-le1+1;
int length2=ri2-le2+1;
if(length1>length2) return findKth(nums2,le2,ri2,nums1,le1,ri1,k);//保证第一个数组比第二个数组短
if(length1==0) return nums2[le2+k-1];//当第一个数组为空时,直接从第二个数组取第k小数
if(k==1) return min(nums1[le1],nums2[le2]);
int i=min(k/2,length1);
int j=min(k/2,length2);
if(nums1[le1+i-1]>nums2[le2+j-1]){
return findKth(nums1,le1,ri1,nums2,le2+j,ri2,k-j);
}
else{
return findKth(nums1,le1+i,ri1,nums2,le2,ri2,k-i);
}
}
};
标签:kth -o amp 中位数 第一个 直接 ndk return code
原文地址:https://www.cnblogs.com/zhangfeng406/p/13168276.html