LeetCode 高级 - 两个排序数组的中位数

两个排序数组的中位数

给定两个大小为 m 和 n 的有序数组 nums1nums2

请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log (m+n)) 。

示例 1:

nums1 = [1, 3]
nums2 = [2]

中位数是 2.0

示例 2:

nums1 = [1, 2]
nums2 = [3, 4]

中位数是 (2 + 3)/2 = 2.5

分析

复杂度为O(m+n)的解法:归并排序。实际就是顺次比较两个数组的元素,取第(nums1.length+nums2.length)/2(下文中以k代替)个元素即可。

考虑O(log(m+n))的复杂度,采用二分的思想:两个数组分别取第k/2个元素(此时先不考虑边界问题),nums1[k/2],nums2[k/2],判断二者的值

  • nums[k/2] < nums2[k/2] :此时中位数位于数组1的右半段和数组2的左半段中,考虑此时数组1左端有k/2个小于中位数的数,数组2右端有k/2个大于中位数的数,因此将两端直接剔除。
  • nums[k/2] > nums2[k/2]:此时中位数位于数组1的左半段和数组2的右半段中,和上面情况相反。
  • nums[k/2] == nums2[k/2]:此时中位数恰好等于任一数组的中点值

详细则需要考虑边界,即数组长度是否大于k/2的问题。

代码

class Solution {
    //找第K小元素的变种
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int size1 = nums1.length,size2 = nums2.length;

        int size = size1+size2;
        //分奇偶处理
        if(size%2 == 1){
            return findKth(nums1,0,nums2,0,size/2+1);
        }else{
            return (findKth(nums1,0,nums2,0,size/2) + findKth(nums1,0,nums2,0,size/2+1))/2;
        }
    }
    /*
    nums1:数组1
    i:数组1起始位置
    nums2:数组2
    j:数组2起始位置
    k:第k小元素
    */
    private double findKth(int[] nums1,int i,int[] nums2,int j,int k){
        //始终让数组1的长度小
        if(nums1.length-i> nums2.length - j){
            return findKth(nums2,j,nums1,i,k);
        }
        //数组1(小的数组)是否为空,空的话,直接在另一个数组中找第K个
        if(nums1.length == i){
            return nums2[j+k-1];
        }
        //k==1时,表示找第一个元素,比较两个数组第一个元素,返回小的即可
        if(k==1){
            return Math.min(nums1[i],nums2[j]);
        }

        //数组1中取mid1个元素,取k/2和数组长度的小者
        int mid1 = Math.min(i+k/2,nums1.length);
        //在数组2中取剩余的 k-mid1个元素,
        int mid2 = j + k - mid1 + i;

        //判断中位数的位置
        if(nums1[mid1-1] < nums2[mid2 - 1]){
            //此时中位数位于数组1右半段和数组2左半段
            return findKth(nums1,mid1,nums2,j,k - mid1 + i);
        }else if(nums1[mid1 - 1]> nums2[mid2 - 1]){
            //此时中位数位于数组1左半段和数组2右半段
            return findKth(nums1,i,nums2,mid2,k-mid2+j);
        }else{
            //此时恰好取到中位数
            return nums1[mid1-1];
        }

    }
}

猜你喜欢

转载自blog.csdn.net/whdalive/article/details/81090187
今日推荐