小知识,大挑战!本文正在参与“程序员必备小知识”创作活动
4. 寻找两个正序数组的中位数
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
示例 1:
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
示例 3:
输入:nums1 = [0,0], nums2 = [0,0]
输出:0.00000
示例 4:
输入:nums1 = [], nums2 = [1]
输出:1.00000
示例 5:
输入:nums1 = [2], nums2 = []
输出:2.00000
提示:
- nums1.length == m
- nums2.length == n
- 0 <= m <= 1000
- 0 <= n <= 1000
- 1 <= m + n <= 2000
解题思路
这题的关键就是用二分法减治,我们对两个数组nums1,nums2各取出前面k/2个数字,故而加起来就是k个、
- 如果nums1[i]>nums2[j](i,j分别为两个k/2长度数组的最后一个下标),说明如果将2个k/2大小组合而成的数组末尾数字一定是nums[i],并且前k个数不可能从nums2的前k/2个元素里面产生,因为比nums2[j]小的最多只有k-2个元素,因为nums1[i]>nums2[j],因此就排除了nums2[j]的前k/2个元素了,这就是二分减治的思路
代码
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int n=nums1.length,m=nums2.length,l=(n+m+1)/2,r=(n+m+2)/2;
return (double)findMedia(nums1,0,nums1.length-1,nums2,0,nums2.length-1,l)/2+
(double)findMedia(nums1,0,nums1.length-1,nums2,0,nums2.length-1,r)/2;
}
public int findMedia(int[] nums1,int l1,int r1,int[] nums2,int l2,int r2,int k) {
int len1=r1-l1+1,len2=r2-l2+1;
if(len1>len2)
return findMedia(nums2, l2, r2, nums1, l1, r1,k);
if(len1==0)
return nums2[l2+k-1];
if(k==1)
return Math.min(nums1[l1],nums2[l2]);
int i=l1+ Math.min(k/2,len1)-1,j=l2+Math.min(k/2,len2)-1;
if(nums1[i]>nums2[j])
return findMedia(nums1, l1, r1, nums2, j+1, r2, k-(j-l2+1));
else return findMedia(nums1, i+1, r1, nums2, l2, r2, k-(i-l1+1));
}
}