1

题目大意:

给出两个已经递增的序列S1和S2,长度分别为N和M,求将它们合并成一个 新的递增序列后的中位数.

算法思路1:

本来想着暴力求解看看可以得多少分,没想到通过了。直接使用一个数组a存储所有输入的元素,然后使用sort排序函数进行排序,然后计算中位数的位置pos,在M+N为偶数的时候为(M+N)/2-1,在M+N为奇数的时候为(M+N)/2,统一起来就是(M+N)/2+(M+N)%2-1。输出a[pos]就结束了。此题甚至都不需要使用long long 来存储数据.

算法思路2:

直接模拟两递增数组合并的思想即可,唯一不同的就是不需要存储,直接判断就行,首先使用a数组存储第一个序列,b数组存储第二个序列,这里的数据还是用long long吧,虽然没有像题目说的那样数据会很大,然后第一个问题就是对于一个长度为n的序列,中位数的位置在哪?我们这里假设数组从1开始存储,那么对于n是偶数的时候,中位数的位置在n/2的地方,当n是奇数的时候,中位数在n/2+1的地方,综合起来就是,对于长度为n的序列,中位数的位置pos=n/2+n%2;然后使用2个指针i和j分别指向a和b
数组,初始都是1,然后依次遍历,在此过程中使用count统计经过的数字个数,如果count==pos说明当前扫描的数就是中位数(为2者中的最小值,原因很简单,如果不是中位数较小者就会首先被遍历然后指针后移,不懂的看看两递增数组合并的过程),如果count!=pos,就让当前较小的数字对应的指针后移(按照合并后的顺序较小者排在前面),同时我们使用num保存中位数,初始化为-1,在退出2序列中退出同时遍历的时候得判断num是否为-1,如果是说明有一个序列太短了,得继续判断没有遍历完毕的序列,最后输出num即可

提交结果:

截屏2020-10-20 下午1.56.26.png

AC代码1:

#include <cstdio>
#include <algorithm>

using namespace std;

int main(){
    int N,M;
    scanf("%d",&N);
    int a[400001];
    for (int i = 0; i < N; ++i) {
        scanf("%d",&a[i]);
    }
    scanf("%d",&M);
    for (int i = N; i < M+N; ++i) {
        scanf("%d",&a[i]);
    }
    int pos = (M+N)/2+(M+N)%2-1;//中位数的位置
    sort(a,a+M+N);
    printf("%d",a[pos]);
    return 0;
}

AC代码2:

#include<cstdio>

using namespace std;

int main(){
    int n;
    scanf("%d",&n);
    long long a[n+1];
    for(int i=1;i<=n;++i){
        scanf("%ld",&a[i]);
    }
    int m;
    scanf("%d",&m);
    long long b[m+1];
    for(int i=1;i<=m;++i){
        scanf("%ld",&b[i]);
    }
    int count = 0;
    int pos = (n+m)/2+(n+m)%2;//这个位置就是最终2个序列合并后的中位数的位置
    int i=1,j=1;
    long long num = -1;//保存中位数 
    while(i<=n&&j<=m){
        ++count;
        if(count==pos){
            if(a[i]<b[j]){
                num = a[i];
            }else{
                num = b[j];
            }
            break;
        }else{
            if(a[i]<b[j]){
                ++i;
            }else{
                ++j;
            }
        }
    } 
    if(num==-1){
        while(i<=n){//第一个序列还有多的数,并且还没有找到中位数 
            ++count;
            if(count==pos){
                num = a[i];
                break;
            }else{
                ++i;
            }
        }
        while(j<=m){//第二个序列还有多的数,并且还没有找到中位数 
            ++count;
            if(count==pos){
                num = b[j];
                break;
            }else{
                ++j;
            }
        }
    }
    printf("%ld",num);
    return 0;
}

乔梓鑫
569 声望17 粉丝

主要分享个人学习经验和心得