题目大意:
给出两个已经递增的序列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即可
提交结果:
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;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。