zoukankan      html  css  js  c++  java
  • 算法第二章上机实践报告

    实践题目 7-3 两个有序序列的中位数 

    问题描述 

    已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数。有序序列,的中位数指A(N1)/2​​的值,即第⌊个数(A0​​为第1个数)。

    输入格式:

    输入分三行。第一行给出序列的公共长度N(0<N≤100000),随后每行输入一个序列的信息,即N个非降序排列的整数。数字用空格间隔。

    输出格式:

    在一行中输出两个输入序列的并集序列的中位数。

    输入样例1:

    5
    1 3 5 7 9
    2 3 4 5 6
    

    输出样例1:

    4
    

    输入样例2:

    6
    -100 -10 1 1 1 1
    -50 0 2 3 4 5
    

    输出样例2:

    1




    算法描述:二分搜索,递归查找两个数组A,B的中位数,(中位数位置 =(Left + Right)/2),
    如果A数组中位数小于B数组中位数递归查找A中间到右边的中位数和数组B左边到中间的中位数,
    如果A数组中位数大于B数组中位数,则递归查找A数组左边到中间的中位数和B数组中间到左边的中位数,

    边界条件是当数组A和数组B元素个数都为2时无法再递归查找中位数时,直接判断数组A和数组B4个元素的中位数,
    判断方法为
    若A第一个元素小于B第一个元素,那么A第一个元素不可能是中位数(因为A第二个元素B第一第二个元素都比A第一个元素大,A第一个元素就一定是最小的),
    接着判断A第二元素和B第一个元素,
    若A第二个元素比B第一个元素小,那么A第二元素就为中位数(说明A第二元素大于A第一元素同时必定小于B第一个和第二个元素,该例子中4个数中第二大的为中位数),
    若A第二元素比B第一个元素大,那么B第一个元素就为中位数(说明B第一个元素小于B第二个元素和A第二个元素,同时B第一个元素又大于A第一个元素,则B第一个元素为中位数)。

    若A第一元素大于B第一个元素,接着判断推理同上类似
    边界判断代码实现:
    if (aRight - aLeft == 1 || bRight - bLeft == 1)
        {
            if (a[aLeft] < b[bLeft])
                return a[aRight] < b[bLeft] ? a[aRight] : b[bLeft];
            else
                return b[bRight] < a[aLeft] ? b[bRight] : a[aLeft];
        }

    在递归查找中位数时调试出现问题,若数组AB元素为奇数时,那么数组AB中间切分时不会出现个数不一样的情况,但若AB数组元素个数为偶数时如为4时,切分数组时会出现个数分别为2和3的情况,
    为了避免这种情况发生,就要舍掉一个元素或者多加一个元素,若A数组中位数小于B数组中位数,二分一半时A会分到 N/2+1元素(N为偶数),而B数组分到N/2个元素(N为偶数),分B数组时多加一个元素就可以让两个数组个数一致,
    让B数组分到BRight到Bmid+1就可以了;若A数组中位数大于B数组中位数,则让A数组从ALeft分到Amid+1即可。
    递归代码实现:
    if (a[medianA] == b[medianB])
                return a[medianA];
            else if (a[medianA] < b[medianB])
            {
                if ((aRight - aLeft + 1) % 2 == 1)
                    return biSearchMedian(a, medianA, aRight,
                        b, bLeft, medianB);
                else
                    return biSearchMedian(a, medianA, aRight,  // medianA + 1? - 1 ?
                        b, bLeft, medianB + 1);
            }
            else
            {
                if ((bRight - bLeft + 1) % 2 == 1)
                    return biSearchMedian(a, aLeft, medianA, 
                        b, medianB, bRight);
                else
                    return biSearchMedian(a, aLeft, medianA + 1,
                        b, medianB, bRight);
            }
        }
    完整函数实现:
    int biSearchMedian(int *a, int aLeft, int aRight, 
        int *b, int bLeft, int bRight)
    {
        int medianA = (aRight + aLeft) / 2;  // (aRight - aLeft + 2) / 2 (x) 第floor((N+1)/2)个数! (aRight - aLeft + 1) / 2(x) 如果这样算下标,第一个例子第二次在函数时madianA = medianB = 1
        int medianB = (bRight + bLeft) / 2;
    
        if (aRight - aLeft == 1 || bRight - bLeft == 1)
        {
            if (a[aLeft] < b[bLeft])
                return a[aRight] < b[bLeft] ? a[aRight] : b[bLeft];
            else
                return b[bRight] < a[aLeft] ? b[bRight] : a[aLeft];
        }
        else
        {
            if (a[medianA] == b[medianB])
                return a[medianA];
            else if (a[medianA] < b[medianB])
            {
                if ((aRight - aLeft + 1) % 2 == 1)
                    return biSearchMedian(a, medianA, aRight,
                        b, bLeft, medianB);
                else
                    return biSearchMedian(a, medianA, aRight,  // medianA + 1? - 1 ?
                        b, bLeft, medianB + 1);
            }
            else
            {
                if ((bRight - bLeft + 1) % 2 == 1)
                    return biSearchMedian(a, aLeft, medianA, 
                        b, medianB, bRight);
                else
                    return biSearchMedian(a, aLeft, medianA + 1,
                        b, medianB, bRight);
            }
        }
    }
    
    

    算法时间及空间复杂度分析

    时间复杂度为Ologn,因为用了二分搜索的方法,范围从一开始n逐步缩减到n/2, n/4... 所以是Olog2n的时间复杂度

    空间复杂度为O1,因为没有用到辅助的空间,所以空间复杂度为O1

    心得体会

    一开始用的是归并的思想,因为已经归好了直接并就行了,但是这样的时间复杂度是On,空间复杂度为On,因为题目要求时间复杂度为OlogN,就只能采取二分搜索了,二分搜索是一种比较快的算法了。

     
  • 相关阅读:
    Dijjer:给流媒体插上 P2P 的同党
    gnomecolorchooser:桌面颜色设置小对象
    LXPanel:轻巧疾速的桌面面板
    批量创立缩略图
    SPE IDE:跨平台的 Python IDE
    主管的信
    使用 TRegistry 类[2]: 读取 IE 浏览器的 Start Page
    用多媒体库 Bass.dll 播放 mp3 [15] 设置与获取播放速度
    用多媒体库 Bass.dll 播放 mp3 [14] 频率均衡器
    用多媒体库 Bass.dll 播放 mp3 [13] 混响(Reverb)效果
  • 原文地址:https://www.cnblogs.com/likeghee/p/11545586.html
Copyright © 2011-2022 走看看