PAT_A1029
PAT甲级1029.
目录
A1029
题目
样例
样例1
输入:
4 11 12 13 14
5 9 10 15 16 17
输出:
13
补充样例
输入:
1 1
1 2
输出:
1
思路和坑点
考虑到数据量比较大,而且直接合并排序的时间比较长,因此单独对每一个进行排序。然后,计算出中位数是第k个,每次从两个序列中弹出一个小的数,直到弹出了k-1个之后,下一个要被弹出的便是中位数。可以使用一个标记来标识在k-1之后只进行一次便推出循环,省去了最后找第k个的的代码重复。
坑点
对于每个序列只有一个的情况,需要特判一下,不然我这个循环会因为这种情况陷入死循环。
AC代码
#include<bits/stdc++.h>
using namespace std;
int main(void){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt","r",stdin);
#endif
vector<int> a,b;
int la,lb,k,cnt=0;
scanf("%d",&la); a.resize(la);
for(int i=0;i<la;i++)
scanf("%d",&a[i]);
scanf("%d",&lb); b.resize(lb);
for(int i=0;i<lb;i++)
scanf("%d",&b[i]);
if(la==1&&lb==1){ //特判每一个序列只有一个数的情况
printf("%d",min(a[0],b[0]));
return 0;
}
sort(a.begin(),a.end()); //对两个序列进行排序
sort(b.begin(),b.end());
int i=0,j=0;
k=(la+lb)%2==0?(la+lb)/2:(la+lb+1)/2; //算出中位数在数列中位于第几个,从1开始算的第k个
while(1){
if(i<la&&j<lb){ //如果两个表都未到头,弹出小的那一个
if(a[i]<=b[j]) i++;
else j++;
}
else if(i<la) i++; //如果有任意一个空了,则从不空的里边弹出一个
else if (j<lb) j++;
cnt++;
if(cnt==k-1) break; //当弹出k-1个的时候,下一个就是第k个了
}
if(i<la&&j<lb) //找到第k个的元素在哪个序列中
printf("%d",min(a[i],b[j]));
else if(i<la)
printf("%d",a[i]);
else if(j<lb)
printf("%d",b[j]);
return 0;
}