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

作者 : XiaXinyu
日期 :2021-09-21

题目

理解

给定两个升序的数组,找出由这两个数组合并后的升序数组中的中位数

题解1(朴素做法——双指针合并数组)

这道题首先我想到的最直观的做法就是利用双指针将两个数组合并成一个有序数组

合并之后在新数组中找出中位数即可

这种做法应该是最容易理解的

伪代码
  • 初始化新数组,长度为给定两个数组的长度之和

  • 初始化指向两个数组的指针i,j以及新数组指针cnt

  • 当 i 小于 nums1的长度时或 j 小于nums2的长度时执行循环

    • 当 i 小于 nums1的长度时,val1等于nums1[i],否则等于int型整数最大值
    • 当 j 小于 nums2的长度时,val2等于nums2[j],否则等于int型整数最大值
    • 如果val1 小于等于 val2则新数组中填入val1指针i 后移
    • 否则新数组中填入val2指针j 后移
    • (注 : 这里让val1 和val2 取整数最大值是由于当 i 或 j >= 所指向数组长度时,那么新数组中只能填入 j 或 i 所指向的值)
  • 判断新数组长度是否为奇数

    • 若为奇数直接返回中间值即可
    • 若为偶数返回中间两个值的平均数即可
代码
class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int[] a = new int[nums1.length + nums2.length];
        int i = 0,j = 0;
        int cnt = 0;
        while(i < nums1.length || j < nums2.length){
            {
                int val1 = i < nums1.length ? nums1[i] : Integer.MAX_VALUE;
                int val2 = j < nums2.length ? nums2[j] : Integer.MAX_VALUE;
                if(val1 <= val2){
                        a[cnt ++] = val1;
                        i ++;
                    }
                else{
                        a[cnt ++] = val2;
                        j ++;
                    }
            }
        
        }
        if(a.length % 2 != 0) return a[a.length / 2];
        
        return 1.0 * (a[a.length / 2] + a[a.length / 2 - 1]) / 2;
    }
}

时间复杂度 :O(n + m) 使用双指针算法,会将两个数组都遍历一遍,n为数组1的长度,m为数组2的长度

空间复杂度 :O(n + m) 开辟新数组的空间为n + m

题解二

题解二的思路来源于这里

在题解一中我们遍历了两个数组的所有元素,其实并不需要这样做,只需要遍历到可确定中位数的元素即可

先讨论一下奇偶性的情况,假设两个数组的总长度为len

当len为奇数时,中位数的位置在len / 2 + 1,

当len为偶数时,中位数为在len / 2 和 len / 2 + 1的两个数的平均值

所以无论len为奇数还是偶数,只需遍历到 len / 2 + 1 个元素即可,将两个数组分别称为A,B

首先初始化astart和bstart分别作为指向A,B数组的指针,left为上一次遍历到的元素值,right为当前遍历的元素值

当astart小于数组A的长度时并且bsatrt > B数组长度或 A[astart] < B[bstart]这两个条件中有一个成立一个令astart右移,否则bstart右移,right的值更新为astart或bstart指针右移之前所指向的值

注意在每次循环时都要让left的值等于right,这样处理后,在遍历结束时,right的值为遍历到最后一个元素的值,left值为最后遍历到最后一个元素的前一个元素的值

class Solution{
    public double findMedianSortedArrays(int[] a, int[] b){
        int right = -1,left = -1;
        int astart = 0,bstart = 0;
        int len = a.length + b.length;
        for(int i = 0;i <= len / 2;i ++){
            left = right;
            if(astart < a.length && (bstart >= b.length || a[astart] < b[bstart]))
            right = a[astart ++];
            else
            right = b[bstart ++];

        }
        if((len & 1) == 0) return (right + left) / 2.0;
        else return right;
    }
    
}

时间复杂度 :O(m + n) 虽然我们遍历了len / 2 + 1次, 但是len = (m + n) / 2,所以时间复杂度仍然为O(m + n)

空间复杂的 :O(1)

题解3(二分法)

待完善

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XiaXinyuuu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值