PAT A1057 Stack (30 分)

题目

1057 Stack (30 分)
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 (≤10
​5
​​ ). 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 10
​5
​​ .

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
Inval

思路

这个是按照书上的hash数组,进行分块来写的。
table[x]的元素代表x元素出现的次数,block[idx]是idx块元素的个数,思路很清晰。
最大maxn个元素,分成sqrt(maxn)块。
对于N次查询,总的时间复杂度为O(N*sqrt(N))。

还有,这次我感受到了先把子函数的定义写出来,把main函数的框架搭好,再写程序比较好

遇到的问题

向上取整的方法

这里由于是除以2,所以可以加0.5向上取整,但是记得需要转换成浮点数

int(st.size() / 2 + 0.6);		//这是不对的
int(st.size() / 2.0 + 0.6);		//这是对的

代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<stack>


using namespace std;
typedef int ElementType;

const int maxn = 100010;
const int sqrN = 316;

stack<ElementType> st;
int table[maxn] = { 0 };
int block[sqrN] = { 0 };//块内元素数目

bool Push(ElementType x) {
	
	st.push(x);
	table[x]++;
	block[x / sqrN]++;
	return true;
};
bool Pop() {
	if (st.size() == 0)    //栈空
	{
		cout << "Invalid" << endl;
		return false;
	}
	ElementType top;
	top = st.top();
	st.pop();
	table[top]--;
	block[top / sqrN]--;
	cout << top << endl;
	return true;
};

//查找第K大的元素
bool peekMedian(int K) {
	if (st.size() == 0)		//栈空
	{
		cout << "Invalid" << endl;
		return false;
	}
	int blo_num=0;	//block number
	int sum=0;		//当前计数
	//找到对应的block
	for (int i = 0; i < sqrN; i++) {
		
		if (sum + block[i] >= K) {
			blo_num = i;
			break;
		}
		sum = sum + block[i];
	}
	int num = blo_num * sqrN;	//该块第一个数
	while ( sum+ table[num] < K) {
		sum = sum + table[num++];

	}
	cout << num << endl;
	return true;

};

int main() {
	//freopen("input.txt", "r+", stdin);
	int n;
	ElementType ele;//input element
	cin >> n;
	for (int i=0; i < n; i++) {
		char cmd[20];//输入命令
		cin >> cmd;
		if (strcmp(cmd, "Pop")==0)
			Pop();
		else if (strcmp(cmd, "PeekMedian") == 0) {
			int a = st.size() / 2.0 + 0.6;
			//cout << a << "error!"<<endl;
			peekMedian(a);
			
		}
		else if (strcmp(cmd, "Push")==0) {
			cin >> ele;
			Push(ele);
		}

	}


	return 0;


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值