力扣第四题几种解题方法--寻找两个有序数组的中位数

第一种:暴力破解
将两个数组整合为一个数组,然后根据整合后数组的长度进行中位数的计算

public double findMedianSortedArrays(int[] nums1, int[] nums2) {
    int m=nums1.length,n=nums2.length;
    int[] result=new int[m+n];
    int flag=0,i=0,j=0;
    while(m>i&&n>j){
        if(nums1[i]<nums2[j]){
            result[flag]=nums1[i];
            i++;
            flag++;
        }
        else{
            result[flag]=nums2[j];
            j++;
            flag++;
        }
    }
    if(i==m)
        for(;j<n;j++,flag++)
            result[flag]=nums2[j];
    else
        for(;i<m;i++,flag++)
            result[flag]=nums1[i];
        for(int k:result)
            System.out.println(k);
        System.out.println(result.length/2+" "+(result.length/2-1));
    if(result.length%2==0)
        return (result[result.length/2]+result[result.length/2-1])/2;
    else
        return result[result.length/2];
}

第二种:并不需要真的进行两个数组的合并,我们只需要找到中位数行营位置的数据就可以,即length/2以及length/2-1 对应位置的数据;

public double findMedianSortedArrays(int[] nums1, int[] nums2) {
    int m=nums1.length,n=nums2.length;
    int i=0,j=0,flag=0,aim=(m+n)/2+1,pre=0,now=0;
    while(flag<aim&&i<m&&j<n){
        if(nums1[i]<=nums2[j]){
            i++;
            if(++flag<aim)
                pre=nums1[i-1];
            else
                now=nums1[i-1];
        }
        else{
            j++;
            if(++flag<aim)
                pre=nums2[j-1];
            else
                now=nums2[j-1];
        }
        System.out.println(now+" "+pre);
    }
    if(i==m&&flag<aim)
    {
        if(aim-flag<=1)
            now=nums2[j+aim-flag-1];
        else{
            pre=nums2[j+aim-flag-2];
            now=nums2[j+aim-flag-1];
        }
    }
    else if(j==n&&flag<aim){
        if(aim-flag<=1)
            now=nums1[i+aim-flag-1];
        else{
            pre=nums1[i+aim-flag-2];
            now=nums1[i+aim-flag-1];
        }
    }
    System.out.println(now+" "+pre);
    if((m+n)%2==0)
        return (double)(now+pre)/2;
    else
        return now;
}

第三种:第k小解题
我们要找的中位数其实就是两个数组中的第length/2个小的数,如果将长度为奇数和长度为偶数的数组统一的话,我们可以得到下面的公式:
中位数=第length/2+1个小的数+第(length+1)/2个小的数(奇数会得到两个相同位置的数,而偶数则得到两个中间位置的数)。寻找第k小由于我们输入的是有序数组就变得很简单;

public int findK(int k,int[] nums1,int[] nums2){
    int m=nums1.length,n=nums2.length;
    int i=0,j=0;

    while(k>=1){
        if(m==0)
            return nums2[j+k-1];
        else if(n==0)
            return nums1[i+k-1];
        else if(k/2>m){
            if(nums1[i+m-1]<nums2[j+m-1])
                return nums2[j+k-m-1];
            else
            {
                k-=m;
                j+=m;
                n-=m;
            }
        }
        else if(k/2>n){
            if(nums1[i+n-1]>nums2[j+n-1])
                return nums1[i+k-n-1];
            else
            {
                k-=n;
                i+=n;
                m-=n;
            }
        }
        else if(k/2==0){
            System.out.println(i);
            if(i==nums1.length)
                return nums2[j];
            else if(j==nums2.length)
                return nums1[i];
            else
                return nums1[i]<nums2[j]?nums1[i]:nums2[j];
        }
        else{
            if(nums1[i+k/2-1]<nums2[j+k/2-1])
            {
                m-=k/2;
                i+=k/2;
                k-=k/2;
            }
            else
            {
                j+=k/2;
                n-=k/2;
                k-=k/2;
            }
        }
    }
    return 0;
}

第四种:根据中位数的性质
中位数的定义就向我们阐述了它的作用,用于将一个集合分割为两部分,根据这个定义我们可以将两个数组分割为两部分,不断的分割,直至我们找到中位数所在的位置(利用二分搜索);从而使得分割后的数组左侧的最大值小于等于右侧的最小值,如果为奇数,中位数就是左侧最大值,反之则为左侧最大值和右侧最小值之和除2;

public double getAim(int[] nums1,int[] nums2){
    int iMin=0,iMax=nums1.length,halfLength=(nums1.length+nums2.length+1)/2;
    while(iMin<=iMax){
        int i=(iMin+iMax)/2;
        int j=halfLength-i;
        if(i<iMax&&nums1[i]<nums2[j-1])
        {
            iMin=i+1;
        }
        else if(i>iMin&&nums1[i-1]>nums2[j])
        {
            iMax=i-1;
        }
        else{
            int leftMax=0;
            if(i==0) leftMax=nums2[j-1];
            else if(j==0) leftMax=nums1[i-1];
            else leftMax=Math.max(nums1[i-1],nums2[j-1]);
            System.out.println(leftMax);
            if((nums1.length+nums2.length)%2!=0) return (double)leftMax;

            int rightMax=0;
            if(i==nums1.length) rightMax=nums2[j];
            else if(j==nums2.length)rightMax=nums1[i];
            else rightMax=Math.min(nums1[i],nums2[j]);
            System.out.println(rightMax);
            return (double)(leftMax+rightMax)/2;
        }
    }
    return 0.0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值