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)),不过这应该是一种可行的求解办法,有错误不足之处欢迎留言批评指正。

  • 相关阅读:
    百度mp3地址解密码
    VB 在EXE后附加信息
    截屏函数
    Base64和StrToByte
    The Android ION memory allocator, DMABUF is mentioned as well
    DDC EDID 介绍
    Memory management for graphic processors TTM的由来
    科普 写display driver的必看 How video card works [2D的四种主要操作]
    GEM vs TTM
    DMABUF 背景介绍文章 Sharing buffers between devices
  • 原文地址:https://www.cnblogs.com/sunupo/p/11239723.html
Copyright © 2011-2022 走看看