题目来源:leetcode4 寻找两个正序数组的中位数
题目描述:
给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。
请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
示例 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
解题思路:
结合二分法。
在两个排序数组中找中位数,数组长度m和n ,求left=(m+n+1)/2和right=(m+n+2)/2位置的值的平均数,可以把问题简化不用考虑奇数偶数。
接着把问题转为为在数组中找第k大的数(k分别为left和right),可以在nums1数组和nums2数组中分别找前k/2个数,如果其中一个第k/2个数小于另一个的第k/2个数,那么第k大数肯定在另一个里面,那么把第k大数不在的数组砍掉k/2,再继续寻找,即每次缩小k/2范围,每次折半删除的都是比第k个数小的,最终找到第k个数。
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m=nums1.size(),n=nums2.size(),left=(m+n+1)/2,right=(m+n+2)/2;
return (findKth(nums1,0,nums2,0,left)+findKth(nums1,0,nums2,0,right))/2.0;
}
int findKth(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 midVal1=(i+k/2-1)<nums1.size()?nums1[i+k/2-1]:INT_MAX;
int midVal2=(j+k/2-1)<nums2.size()?nums2[j+k/2-1]:INT_MAX;
if(midVal1<midVal2)
return findKth(nums1,i+k/2,nums2,j,k-k/2);
else return findKth(nums1,i,nums2,j+k/2,k-k/2);
}
};