• 算法第二章上机实践报告


    7-3 两个有序序列的中位数 (20 分)

    已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数。有序序列,的中位数指A(N1)/2​​的值,即第(N+1)/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


    题意:把两个数组按非递减的顺序合起来后求中位数。

    解题思路(算法描述):因为两个数组本身有序,可对两个数组进行二分。
    我们不断维护两个数组的二分区间la,ra和lb,rb,保证两个区间中元素个数相同
    定义:
    第一个数组名为a, ai表示数组第i个元素, 第二个数组名为b, bi表示数组第i个元素
    ma=(la+ra)/2, mb=(lb+rb)/2
    根据定义,可以知道当l到r之间的元素为奇数个时ma + mb = n + 1
    当l到r之间的元素为偶数个时ma + mb = n

    1.二分的时候遇到a[ma] == b[mb]的时候
    若l到r元素个数为偶数 ma + mb = n
    我们把a[1]到a[ma],b[1]到b[mb]的元素拼起来,共n个元素,其中第n个元素就是问题答案
    因为原数组有序,所以a[ma]和b[mb]肯定是该数组最大的数,而a[ma+1]和b[mb+1]都是大于等于新数组的所以元素,故无需考虑ma,mb之后的数了
    若l到r元素个数为奇数 ma + mb = n + 1
    同上,a[ma]和b[mb]必为答案

    2.二分的时候遇到a[ma] > b[mb]的时候
    因为a[ma+1] >= a[ma] > b[mb]
    比a[ma+1]小的元素肯定大于等于n个
    所以数组a的区间ma+1到r的元素不用考虑了
    所以ra = ma,la = mb,调整二分区间,然后继续二分,b[mb] > a[ma]同理
    注意让两个区间的个数相等

    参考代码
    #include <iostream>
    #include <math.h>
    using namespace std;
    int a[100010],b[100010],n;
    int find(int la,int ra,int lb,int rb)
    {
        if (la == ra) {
            if (a[la] == b[lb]) return a[la];
            else return a[la] > b[lb] ? b[lb] : a[la];
        }
        int ma = la + ra >> 1;
        int mb = lb + rb >> 1;
        if (a[ma] == b[mb]) return a[ma];
        else if (a[ma] > b[mb]) {
            ra = ma;
            lb = mb;
            if(ra - la != rb - lb) lb++;
            return find(la,ra,lb,rb);
        }
        else {
            rb = mb;
            la = ma;
            if(ra - la != rb - lb) la++;
            return find(la,ra,lb,rb);
        }
    }
    int main()
    {
    
        ios::sync_with_stdio(0);
        cin >> n;
        for(int i=1; i<=n; ++i) cin >> a[i];
        for(int i=1; i<=n; ++i) cin >> b[i];
        a[0] = b[0] = -199999999;
        cout << find(1,n,1,n);
        return 0;
    } 
    View Code
    算法分析
      时间复杂度:数组长度为n,所以二分的时间复杂度是O(logn),输入数据的时间复杂度是O(n),所以算法时间复杂度是O(logn)(强行口胡)
      空间复杂度:只开了4个变量,显然O(1)
            
    心得体会
      写二分一定要思路清晰,不然很容易出问题,要知道l,r该怎么移动,为什么这样移动。

  • 相关阅读:
    Search a 2D Matrix leetcode java
    Sqrt(int x) leetcode java
    Search for a Range leetcode java
    php获取客户端公网ip代码
    ddns+ros(routeros)+centos7.6+nginx+php+dnspod
    limits.conf文件修改注意事项,限制文件描述符数和进程数
    阿里云本地存储网关的一些特点和注意事项
    ROS根据访问不同的网址,走不同的路由策略的脚本
    漫威所有电影的 按时间线的观影顺序
    sklearn—特征工程
  • 原文地址:https://www.cnblogs.com/Remilia-Scarlet/p/11556996.html
Copyright © 2020-2023  润新知