1057 Stack (30 分)-PAT甲级

本文介绍了如何实现一个带有PeekMedian操作的栈,其中PeekMedian返回栈中所有元素的中位数。通过维护一个映射记录元素出现次数和迭代器指向中位数位置,利用中位数查找算法在Push和Pop操作后动态调整中位数位置。在给定的输入样本中,展示了如何根据输入命令正确地执行栈操作并输出结果。
摘要由CSDN通过智能技术生成

Stack is one of the most fundamental data structures, which is based on the principle of Last In First Out (LIFO). The basic operations include Push (inserting an element onto the top position) and Pop (deleting the top element). Now you are supposed to implement a stack with an extra operation: PeekMedian -- return the median value of all the elements in the stack. With N elements, the median value is defined to be the (N/2)-th smallest element if N is even, or ((N+1)/2)-th if N is odd.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤105). Then N lines follow, each contains a command in one of the following 3 formats:

Push key
Pop
PeekMedian

where key is a positive integer no more than 105.

Output Specification:

For each Push command, insert key into the stack and output nothing. For each Pop or PeekMedian command, print in a line the corresponding returned value. If the command is invalid, print Invalid instead.

Sample Input:

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

Sample Output:

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

 题目大意:模拟栈,实现相应功能

1.Push:将指定元素压入栈

2.Pop:如果栈不为空,将栈顶元素输出并弹出,如果栈为空,就输出Invalid

3.PeekMedian:如果栈为空,就输出Invalid,如果栈不为空,设栈中总元素的个数为N,如果N为偶数,就输出栈中第N/2大的元素,如果N为奇数,就输出栈中第(N+1)/2大的元素

思路:Push操作和Pop操作很简单,下面讲讲PeekMedian操作

1.维护一个map,key为栈中元素,value为该元素的个数,定义一个迭代器mid,指向 

PeekMedian要输出元素的位置,beforemid为比mid指向元素小的元素总个数,Push或者Pop操作都有可能改变mid和beforemid的参数,但由于每次Push或者Pop操作都只会增加或者减少一位数,因此mid的移动也是常数级的(mid每次最多移动一个单位长度),根据beforemid的变化和栈的中间位置的元素下标mid_pos就可以判断mid的移动方向,此方法可行。

2.mid移动方向判断:若beforemid >= midpos,mid左移,即mid--,同时更新beforemid的值:beforemid -= mid->second;若beforemid + mid->second < midpos,先更新beforemid的值:beforemid += mid->second,再右移mid,即mid++,其他情况mid不移动。

3.当指令为PeekMedian时,这样只需要输出mid->first的值即可

AC代码 

#include <iostream>
#include <stack> 
#include <map> 
using namespace std;
map<int, int> m; // key为栈中元素,value为该元素个数 
stack<int> s;
map<int, int> :: iterator mid; // mid始终指向中间元素位置 
int beforemid; // 为小于mid指向元素的个数总和 
void adjustmid() {
	// midpos为栈的中间位置
	// 无论栈元素个数总和是奇数还是偶数,均满足下面表达式 
	int midpos = (s.size() + 1) / 2;
	if (beforemid >= midpos) { // 此情况mid左移 
		mid--;
		beforemid -= mid->second; // 更新beforemid的值 
	} else if (beforemid + mid->second < midpos) { // 此情况mid右移 
		beforemid += mid->second; // 更新beforemid的值 
		mid++;
	}
}
int main() {
	int n;
	cin >> n;
	while (n--) {
		string command;
		cin >> command;
		if (command == "Push") {
			int temp;
			cin >> temp;
			m[temp]++;
			s.push(temp);
			if (s.size() == 1) { // 对map相关进行初始化 
				beforemid = 0;
				mid = m.begin();
			} else {
				if (temp < mid->first) {
					beforemid++; // 更新beforemid 
				}	
			}
            adjustmid(); //调整mid 
		}
		else if (command == "Pop") {
			if (s.empty()) {
				cout << "Invalid" << endl;
			} else {
				int temp = s.top();
				cout << temp << endl;
				s.pop();
				m[temp]--;
				if (temp < mid->first) { // 更新beforemid 
					beforemid--;
				}	
                adjustmid(); //调整mid
				if (m[temp] == 0) {
					m.erase(temp);
                }
			}
		} else if (command == "PeekMedian") {
			if (s.empty()) {
				cout << "Invalid" << endl;
			} else {
				cout << mid->first << endl; //输出mid指向的元素 
			}
		}
	}
	return 0;
}

 更多PAT甲级题目:请访问PAT甲级刷题之路--题目索引+知识点分析(正在进行),感谢支持!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值