golang 数组组合成最小的整数_LeetCode4. 寻找两个正序数组的中位数

9ec9f2f29b21e7a85c6be6a5402f6615.png
【题目】 :难度级别[困难]

给定两个大小为 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

[思路]
题目的要求时间复杂度 O(log(m+n)。看到 log,很明显,我们要考虑用二分的方法。
我们需要将两个数组进行切分,分成两个部分---左半部分和右半部分.
将i的左边和j的左边组合成[左半部分],将i的右边和j的右边组合成[右半部分].
1.当A数组和B数组的总长度是偶数时,如果我们能保证,左半部分的长度等于右半部分,
左半部分最大值小于等于右半部分的值max(A[i-1],B[j-1])<=min(A[i],B[j])
那么,中位数就是(左半部分最大值+右半部分最小值)/2。
2.当A数组和B数组的总长是奇数时,如果我们能保证,左半部分的长度比右半部分的大1,
左半部分最大值小于等于右半部分最小的值,那么中位数就是,左半部分最大值。
3.由于A数组和B数组是有序的,所以,A[i-1]<=A[i],B[i-1]<=B[i]一定成立,因此,只需
保证B[j-1]<=A[i]和A[i-1]<=B[j],所以分两种情况讨论:
3.1.B数组左边最大值大于A数组右边最小值,B [j - 1] > A [i],我们需要增加 i ,
为了数量的平衡还要减少 j .
3.2.A数组左边最大值大于B数组右边最小值,A [i - 1] > B [j],此时和上边的情况相反,
我们要减少i,增大j 。
//此方法leetCode提交,超时,不服,又提交两次依然超时
class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int m=nums1.length,n=nums2.length;//保证被切的数组元素个数最少
        if(m>n){
            return findMedianSortedArrays(nums2,nums1);
        }
        int leftArrLen=(m+n+1)/2;//初始化左数组组长度
        int l=0,r=m;
        int leftMax=Integer.MIN_VALUE,rightMin=Integer.MAX_VALUE;
        int c1,c2,n2rightMin,n2leftMax,n1leftMax,n1rightMin;
        while(l<=r){
            c1=(1+r)/2;//数组1切点。。。这个地方写错了,也没有报错,导致后边修bug n个小时
            c2=leftArrLen-c1;//数组2切点
            //边界条件讨论
            n1leftMax=c1==0?Integer.MIN_VALUE:nums1[c1-1];
            n1rightMin=c1==m?Integer.MAX_VALUE:nums1[c1];
            n2leftMax=c2==0?Integer.MIN_VALUE:nums2[c2-1];
            n2rightMin=c2==n?Integer.MAX_VALUE:nums2[c2];
            //如果满足左边数组小于右边数组
            if(n1leftMax<=n2rightMin&&n1rightMin>=n2leftMax){
                leftMax=Math.max(n1leftMax,n2leftMax);
                rightMin=Math.min(n1rightMin,n2rightMin);
                break;
            }else if(n1leftMax>n2rightMin){//切点不合要求
                r=c1-1;//右边界向左
            }else{
                l=c1+1;//左边界向右
            }
        }
        return (m+n)%2==0?(leftMax+rightMin)*0.5:leftMax;//判断总个数,进行中位数计算
    }
}
时间复杂度符合题目要求;空间复杂度O(1)

463dc1e019ebd09815bdac956f29f170.png
为什么我的眼里常含泪水,因为我对知识一无所知。

经过n小时的调试,终于发现了问题所在

原来把while循环中的小写字母l写成了1 !!!

贴出正确代码及运行结果

da27e122c190bb1ead2095aae962f5b7.png
//正确代码(java)
class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int m=nums1.length,n=nums2.length;
        if(m>n){
            return findMedianSortedArrays(nums2,nums1);
        }
        int leftArrLen=(m+n+1)/2;
        int l=0,r=m;
        int leftMax=Integer.MIN_VALUE,rightMin=Integer.MAX_VALUE;
        int c1,c2,n2rightMin,n2leftMax,n1leftMax,n1rightMin;

        while(l<=r){
            c1=(l+r)/2;
            c2=leftArrLen-c1;
            n1leftMax=c1==0?Integer.MIN_VALUE:nums1[c1-1];
            n1rightMin=c1==m?Integer.MAX_VALUE:nums1[c1];
            n2leftMax=c2==0?Integer.MIN_VALUE:nums2[c2-1];
            n2rightMin=c2==n?Integer.MAX_VALUE:nums2[c2];

            if(n1leftMax<=n2rightMin&&n1rightMin>=n2leftMax){
                leftMax=Math.max(n1leftMax,n2leftMax);
                rightMin=Math.min(n1rightMin,n2rightMin);
                break;
            }else if(n1leftMax>n2rightMin){
                r=c1-1;
            }else{
                l=c1+1;
            }
        }
        return (m+n)%2==0?(leftMax+rightMin)*0.5:leftMax;
    }
}

3b42cded55a21b91be6f85ef99b2a534.png
奈何本人没文化,一句N啤走天下
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值