set/list实战——7-53 两个有序序列的中位数(25 分)

199 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第31天,点击查看活动详情

题目描述:

已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数。有序序列A0​,A1​,⋯,AN−1​的中位数指A(N−1)/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

代码长度限制   16 KB

时间限制     400 ms

内存限制     64 MB

PS: 这里讲两种方法:

  • 1.使用list头文件
  • 2.使用set头文件

list思路:

思路分析:

1.创建两个list用来存储两行的数据

2.创建两个list的迭代器用来标记两个list的头部

3.迭代,比较(注意:只需要比较前n个,因为是中位数)

4.输出

list思路代码:

#include<iostream>
#include<list>
using namespace std;
int main()
{
	//创建两个list
	list<int>a, b;
	int n, x;
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> x;
		a.push_back(x);
	}
	for (int i = 0; i < n; i++) {
		cin >> x;
		b.push_back(x);
	}
	int temp;
	list<int>::iterator p = a.begin();
	list<int>::iterator q = b.begin();
	for (int cnt = 0; cnt < n; cnt++) {
		if (*p > *q) {
			temp = *q;
			q++;
		}
		else {
			temp = *p;
			p++;
		}
	}
	cout << temp;
}

提交结果:

image.png

结果分析:

耗时:71ms
内存:6728KB

set思路:

思路分析:

1.由于set具有自动排序的功能,但注意到有重复数字,所以只需要创建一个multiset,让2*n个数字一同放入multiset中

2.迭代multiset,找到中位数

set思路代码:

#include<iostream>
#include<set>
using namespace std;
int main()
{
	int n, x;
	cin >> n;
	multiset<int>s;
	for (int i = 0; i < 2 * n; i++) {
		cin >> x;
		s.insert(x);
	}
	multiset<int>::iterator it = s.begin();
	for (int i = 0; i < n - 1; i++) {
		it++;
	}
	cout << *it;
}

提交结果:

image.png

结果分析:

耗时:103ms
内存:9808KB

两种思路比较:

毫无疑问,list在这里更胜一筹,因为这两个list是基本有序的,所以用list只需要迭代n个就可以找到中位数

反观set由于两个加在一起需要排序,浪费了很多时间,效率不高 PS: 这边建议使用list思路代码~