zoukankan      html  css  js  c++  java
  • 寻找两个有序数组的中位数

    原题目:

      给定两个大小为m,n的有序数组nums1和nums2,找出这两个有序数组的中位数,要求时间复杂度为O(log(m+n)).

      eg:nums1=[1,3];nums2=[2];中位数是2.0

      nums1=[1,2];nums2=[3,4];中位数是(2+3)/2=2.5

    不考虑时间复杂度,简单做法就是把nums1和nums2两个数组的并集重新排序,取得中位数。

    基本思想:
    需要求的中位数mid是把两个数组并集构成的数组num3的元素分为数目相等的两部分。设小于mid的元素构成集合C。
    计算两个数组元素总长度sumLen
    需要向C中添加的元素长度为(sumLen+1)/2 向下取整

       最开始仍需要添加到C中元素的长度为want=(sumLen+1)/2 向下取整,取索引值为indexa=indexb=want/2;

     

    比较nums1[indexa]与nums2[indexb]的大小(谁数值大,谁索引二分),假设nums1[indexa]<nums2[indexb],就对nums2再次进行二分找元素,直到nums1[indexa]>nums2[indexb],

    假设indexb连续二分两次过后(indexb=indexb/2),nums1[indexa]>nums2[indexb],

          然后把nums1索引z为indexa和indexa之前的indexa+1个元素和nums2索引为indexb和indexb之前的indexb+1个元素添加到数组C中,

    更新want的值,计算want=(sumLen+1)/2-indexa-1-indexb-1。

    记录上一次indexa和indexb的值为,indexa1=indexa,indexb1=indexb

    更新indexa,indexb,indexa=indexa1+want/2,indexb=indexb+want/2

    假设nums1[indexa]还是小于nums2[indexb],就对nums2再次进行二分找元素,直到nums1[indexa]>nums2[indexb],

    假设indexb一次二分过后,nums1[indexa]>nums2[indexb],然后把nums1索引为indexa1之后和indexa之前的元素(左开右闭)和nums2索引为indexb1之后和indexb之前的元素(左开右闭)添加到数组C中,

    重复做下去,直到indexa+1+indexb+1 = sumLen/2

      如果sumLen为奇数,说明nums[index+1]与nums2[indexb+1]两个元素较小的那个元素就是最终数组nums3的中位数,结束。

      如果sumLen为偶数,记录nums[indexa]与nums[indexb]中较大的值为c1,记录nums[indexa+1]与nums[indexb+1]中较小的值为c2,最终数组nums3的中位数为(c1+c2)/2

    思路:
    假设两个数组nums1与nums2都不为空(其中一个数组为空就比较简单)
    第零步:计算两个数组的总长度sumLen=nums1.length+nums2.length
        int indexa=-1,indexb=-1;
        int indexa1=-1,,indexb1=-1;
        设nums1与nums2合并后得到的数组为nums3,nums3中位数之前的元素构成数组C,C最终的的长度为(sumLen+1)/2
        计算仍需向数组C添加元素的个数为want(最开始want=(sumLen+1)/2-indexa-1-indexb-1),
    第一步:判断两个数组的中位数是否相等?
        相等,两个有序数组的中位数就是原来各自数组的中位数。
        不相等,进入第二步。
    第二步:
    
        从nums1和nums2中各自取出indexa和indexb后面的want/2个元素进行比较(这儿需要判断indexa和indexb后面总数组元素长度和want/2的大小关系),再计算indexa或者indexb
        //更新indexa与indexb的值
        if(nums1.length-1<indexa+want/2){//eg: 0,9 1,7 2,3 3,2 4,4。length=5 want/2=5,indexa=-1,不满足,直接进入第三种情况
            indexb=indexb+want-(nums1.length-1-indexa);//当indexa=nums1.length-1;indexb=indexb+want;
            indexa=nums1.length-1;
        }else if( (indexb+want/2) > (nums2.length-1)){
            indexa=indexa+want-(nums2.length-1-indexb);
            indexb=nums2.length-1;
        }else{
            indexa=indexa+want/2; indexb=indexb+want/2;
        }
            
    
    
    第三步:比较nums1[indexa]与nums2[indexb]的大小(谁大谁二分),
        ①如果,nums1[indexa]<nums2[indexb],就对nums2再次进行二分找元素(if indexb=indexb1+1,indexb=indexb1,else indexb=(indexb-indexb1+1)/2-1),直到nums1[indexa]>nums2[indexb],
            ①退出循环时,当indexb>=indexb1+1,证明能找到一个nums2[indexb],然后把nums1索引为indexa1+1到indexa的indexa+1个元素和nums2索引为indexb+1到indexb的indexb+1个元素添加到数组C中,
                计算want=(sumLen+1)/2-indexa-1-indexb-1。
                更新indexa1,indexb1;indexa1=indexa;indexb1=indexb;
            ②退出循环时,当indexb=indexb1,说明nums1[indexa]小于等于nums2还没有添加到C中的那部分元素的第一个元素,就把nums1数组的nums1[indexa1+1]到nums1[indexa]之前的元素添加到C中,
                计算want=(sumLen+1)/2-indexa-1-indexb-1.
                更新indexa1,indexb1;indexa1=indexa;indexb1=indexb;
        ②如果,nums2[indexb]<nums1[indexa],就对nums1再次进行二分查找元素,同理。
    第四步:判断sumLen的奇偶性
        ①如果sumLen为奇数,判断indexa+1+indexb+1与(sumLen-1)/2大小,或者与sumLen/2的大小,因为奇数时,(sumLen-1)/2=sumLen/2
            ①indexa+1+indexb+1 = (sumLen-1)/2 ,说明nums[index+1]与nums2[indexb+1]两个元素较小的那个元素就是最终数组nums3的中位数,结束。
            ②indexa+1+indexb+1 < (sumLen-1)/2,
            
            indexa1=indexa;indexb1=indexb;//记录上次indexa、indexb的值
            回到第二步
            //更新indexa、indexb的值
                if( (indexa+want/2) > (nums1.length-1) ){
                    indexb=indexb+want-(nums1.length-1-indexa);
                    indexa=nums1.length-1;
                }else if( (indexb+want/2) > (nums2.length-1)){
                    indexa=indexa+want-(nums2.length-1-indexb);
                    indexb=nums2.length-1;
                }else{
                    indexa=indexa+want/2; indexb=indexb+want/2;
                }
            比较nums1[indexa]与nums2[indexb]的大小(谁大谁二分),
        ②如果sumLen为偶数,判断indexa+1+indexb+1与sumLen/2大小
            ①indexa+1+indexb+1 = sumLen/2,记录nums[indexa]与nums[indexb]中较大的值为c1,记录nums[indexa+1]与nums[indexb+1]中较小的值为c2,最终数组nums3的中位数为(c1+c2)/2,结束。
            ②indexa+1+indexb+1 < sumLen/2,
                indexa1=indexa;indexb1=indexb;//记录上次indexa、indexb的值
                回到第二步

     时间复杂度好像不满足O(log(m+n)),不过这应该是一种可行的求解办法,有错误不足之处欢迎留言批评指正。

  • 相关阅读:
    再次梳理css3动画部分知识
    node搭环境
    微信小程序可用的第三方库
    省市区三级联动下拉框效果分析
    jq回到顶部效果分析
    jq案例中遇到的知识点总结(会飞的小鸟和三级联动)
    js正则表达式大全
    js中表达式 >>> 0 浅析
    为什么js中要用void 0 代替undefined
    npm install、npm install --save、npm install --save --dev、npm install -S、npm install -D的区别
  • 原文地址:https://www.cnblogs.com/sunupo/p/11239723.html
Copyright © 2011-2022 走看看