我的PAT-ADVANCED代码仓:https://github.com/617076674/PAT-ADVANCED
原题链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805466364755968
题目描述:
题目翻译:
1029 中位数
给定N个整数的递增序列S,中位数是中间位置的数字。 例如,S1 = {11,12,13,14}的中位数为12,S2 = {9,10,15,16,17}的中位数为15。两个序列的中位数定义为非递减序列的中值,包含两个序列的所有元素。 例如,S1和S2的中位数是13。
给定两个递增的整数序列,你需要找到它们的中位数。
输入格式:
每个输入文件包含一个测试用例。每个测试用例占两行,每行给出了序列的信息。对每个序列,其第一个正整数N(<= 2 * 10 ^ 5),代表序列的大小。接下来的N个整数由一个空格分隔。题目保证所有的整数都在long int类型范围内。
输出格式:
对每个测试用例,你需要输出两个给定序列的中位数。
输入样例:
4 11 12 13 14
5 9 10 15 16 17
输出样例:
13
知识点:双指针
思路:双指针遍历两个序列即可
本题只需双指针遍历两个序列即可。但是如果用数组或是vector来存储两个序列,测试点8会内存超限。因此我们使用队列来存储两个序列。
在读入第二个序列的同时,和第一个序列开始进行比较,每读入一个新值,队列1或队列2就会有一个值出队列。一旦出队列的元素达到了中位数的索引值(N1 + N2 - 1) / 2,就找到了该中位数,直接return。
需要注意的是,读取完第二个序列后我们未必已经找到了中位数。如果还没有找到中位数,需要继续对两队列进行出队操作寻找中位数。
一个小技巧是,读取完每个序列之后为该序列入队一个INF数据,INF = 0x7fffffff,为long int型的最大值,这样可以避免对某个队列为空的情况进行讨论。
C++代码:
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
int INF = 0x7fffffff;
int main() {
int N1, N2;
scanf("%d", &N1);
queue<int> nums1, nums2;
int num;
for(int i = 0; i < N1; i++) {
scanf("%d", &num);
nums1.push(num);
}
nums1.push(INF);
scanf("%d", &N2);
int count = 0;
for(int i = 0; i < N2; i++) {
scanf("%d", &num);
nums2.push(num);
if(count == (N1 + N2 - 1) / 2){
printf("%d\n", min(nums1.front(), nums2.front()));
return 0;
}
if(nums1.front() <= nums2.front()){
nums1.pop();
}else{
nums2.pop();
}
count++;
}
nums2.push(INF);
for(; count < (N1 + N2 - 1) / 2; count++) {
if(nums1.front() < nums2.front())
nums1.pop();
else
nums2.pop();
}
printf("%d", min(nums1.front(), nums2.front()));
return 0;
}
C++解题报告: