特殊堆栈 (30 分)

3-3-6 特殊堆栈 (30 分)

堆栈是一种经典的后进先出的线性结构,相关的操作主要有“入栈”(在堆栈顶插入一个元素)和“出栈”(将栈顶元素返回并从堆栈中删除)。本题要求你实现另一个附加的操作:“取中值”——即返回所有堆栈中元素键值的中值。给定 N 个元素,如果 N 是偶数,则中值定义为第 N/2 小元;若是奇数,则为第 (N+1)/2 小元。

输入格式:

输入的第一行是正整数 N(≤105)。随后 N 行,每行给出一句指令,为以下 3 种之一:

Push key
Pop
PeekMedian

其中 key 是不超过 105 的正整数;Push 表示“入栈”;Pop 表示“出栈”;PeekMedian 表示“取中值”。

输出格式:

对每个 Push 操作,将 key 插入堆栈,无需输出;对每个 PopPeekMedian 操作,在一行中输出相应的返回值。若操作非法,则对应输出 Invalid

输入样例:

17
Pop
PeekMedian
Push 3
PeekMedian
Push 2
PeekMedian
Push 1
PeekMedian
Pop
Pop
Push 5
Push 4
PeekMedian
Pop
Pop
Pop
Pop

输出样例:

Invalid
Invalid
3
2
2
1
2
4
4
5
3
Invalid

特殊堆栈 (30 分)_第1张图片

超时代码:

#include
#include
#include
using namespace std;
int main()
{
	vector<int>v, v1;
	string opr;
	int n; cin >> n;
	while (n--)
	{
		cin >> opr;
		if (opr.compare("Push") == 0)
		{
			int data; cin >> data;
			v.push_back(data);
		}
		else if (opr.compare("Pop") == 0)
		{
			if (!v.empty())
			{
				cout << v.back() << endl;
				v.pop_back();
			}
			else cout << "Invalid\n";
		}
		else if (opr.compare("PeekMedian") == 0)
		{
			if (v.empty())
				cout << "Invalid\n";
			else
			{
				v1.clear();
				for (auto x : v)
					v1.push_back(x);
				sort(v1.begin(), v1.end());
				if (v1.size() % 2 != 0)
					cout << v1[(v1.size() - 1) / 2] << endl;
				else
					cout << v1[v1.size() / 2 - 1] << endl;
			}
		}
	}
	return 0;
}

特殊堆栈 (30 分)_第2张图片

AC代码:

#include
#include
#include
using namespace std;
int main()
{
	vector<int>v, v1;
	string opr;
	int n; cin >> n;
	vector<int>::iterator it;
	while (n--)
	{
		cin >> opr;
		if (opr.compare("Push") == 0)
		{
			int data; cin >> data;
			v.push_back(data);
			it = lower_bound(v1.begin(), v1.end(), data);
			v1.insert(it, data);
		}
		else if (opr.compare("Pop") == 0)
		{
			if (!v.empty())
			{
				it = lower_bound(v1.begin(), v1.end(), v[v.size() - 1]);
				v1.erase(it);
				cout << v.back() << endl;
				v.pop_back();
			}
			else cout << "Invalid\n";
		}
		else if (opr.compare("PeekMedian") == 0)
		{
			if (v.empty())
				cout << "Invalid\n";
			else
			{
				if (v1.size() % 2 != 0)
					cout << v1[(v1.size() - 1) / 2] << endl;
				else
					cout << v1[v1.size() / 2 - 1] << endl;
			}
		}
	}
	return 0;
}

两个代码的区别就在于排序,前者使用sort函数对vector内的元素进行排序,后者使用了类似插入排序的方式排序,前者在需要PeekMedian操作时就要进行一次排序,数据较多时超时是必然的,后者是对数据进行了优化处理,让排序的花销不太大,在PeekMedian操作时能够使用较小的代价完成目标操作。

你可能感兴趣的:(pta好题)