【LeetCode4】寻找两个有序数组的中位数

思路1:将两个数组按照索引i与索引j切分为左右两个部分,左半部分与右半部分的元素数量相同,并且寻找到左半部分最大值小于右半部分最小值的位置,中位数就在附近,具体的根据总长度是偶数/奇数确定。寻找索引的过程为二分。时间复杂度为O(logmin(shortLength,longLength))

https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xun-zhao-liang-ge-you-xu-shu-zu-de-zhong-wei-shu-b/

思路2:转换为寻找第k小的数字,相当于对两个数组分别寻找第k/2小的数字,由于两个数组都是有序的,所以可以直接根据下标对不可能是第k/2小的数字进行删除,该操作的时间复杂度为O(1)。由于是二分删除,所以时间复杂度为O(log((m+n)/2)),即O(log(m+n))。

https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-2/

以下是思路一的代码:

    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        if(nums1==null||nums2==null||(nums1.length==0&&nums2.length==0)) return 0.0;
        //如果一个数组为空,就变成了寻找单个有序数组的中位数问题,单独写了一个简单的方法
        if(nums1.length==0) return getMiddleNum(nums2,0,nums2.length-1);
        if(nums2.length==0) return getMiddleNum(nums1,0,nums1.length-1);
        int totalLength=nums1.length+nums2.length;

        //设置较长数组与较短数组及其长度
        int[] shortArray,longArray;
        int shortLength,longLength;
        if(nums1.length<nums2.length){
            shortArray=nums1;
            longArray=nums2;
        }
        else{
            shortArray=nums2;
            longArray=nums1;
        }
        shortLength=shortArray.length;
        longLength=longArray.length;

        //搜索边界为[-1,短数组的最后一个元素],索引为i时,隔板放在第i个元素之后
        int left=-1,right=shortLength-1;
        int i,j;
        //短数组左半部分最大值,长数组左半部分最大值,短数组右半部分最小值,长数组右半部分最小值
        int max1=0,max2=0,min1=0,min2=0;
        //左半部分最大值,右半部分最小值
        int leftMax=0,rightMin=0;

        while(left<=right){
            i=(left+right)/2;
            j=(int)(totalLength/2.0+0.5)-(i+1)-1;
            //获得左半部分的最大值
            max1=i>=0&&i<shortLength?shortArray[i]:Integer.MIN_VALUE;
            max2=j>=0&&j<longLength?longArray[j]:Integer.MIN_VALUE;
            leftMax=Math.max(max1,max2);
            //获得右半部分的最小值
            min1=(i+1)>=0&&(i+1)<shortLength?shortArray[i+1]:Integer.MAX_VALUE;
            min2=(j+1)>=0&&(j+1)<longLength?longArray[j+1]:Integer.MAX_VALUE;
            rightMin=Math.min(min1,min2);

            if(leftMax<=rightMin){
                break;
            }
            else if(max1>min2){
                right=i-1;
            }
            else if(max2>min1){
                left=i+1;
            }
        }
        return totalLength%2==0?(leftMax+rightMin)/2.0:leftMax;
    }

寻找单个有序序列的中位数

    public double getMiddleNum(int[] nums, int left, int right){
        if(left>right) return -1;

        int middle=(left+right)/2;
        boolean flag=(right-left+1)%2==0?true:false;
        if(flag){
            return (nums[middle]+nums[middle+1])/2.0;
        }
        else{
            return nums[middle];
        }
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值