4. 寻找两个正序数组的中位数

113 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

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

image.png

解题思路

这题的关键就是用二分法减治,我们对两个数组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));
    }
}