更多PAT甲级题解--acking-you.gtihub.io
最易理解的Stack实现方式,没有树状数组,没有堆!
题目
题目分析
- 关键就是要我们实现以下这个操作:
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. 作用是返回栈中第 N/2 小的元素。
- 我们可能很快就会想到排序,然后用STL中的栈来实现,一旦需要排序的时候(PeekMedian操作)就直接sort,然后提交后你会发现----它超时了!😂
好吧,我不偷懒了,自己想想怎么实现这一一个栈,我是用的最朴素的方式实现,通过在栈中多加一个数组实现对元素的排序(这个过程由于是每次入栈和出栈进行排序,所以完全可以用二分找到位置进行插入和删除某个元素),后面看到很多大佬,不是用堆就是用树状数组,太强了,我还达不到这样的高度啊🤦♂️
- 以下是我实现的效率(根大佬们的树状数组还是没得比🤣
代码详解
栈的数据结构实现
这里使用的二分是STL自带的,当然你也可以自己写个二分,这样的话,代码长度会变长🤦♂️
//@实现一个栈,用两个数组实现。
struct Stack {
int *nums; //用作栈空间
int *sort_nums; //将栈元素排序后的情况
int length; //栈的长度
int capcity; //栈的最大容量
Stack(int cap) : nums(nullptr), length(0), capcity(cap), sort_nums(nullptr) {
nums = new int[capcity];
sort_nums = new int[capcity];
}
//@关键在于push和pop操作的处理
void push(int val) {
if (!isEmpty()) {
int pos = upper_bound(sort_nums, sort_nums + length, val) - sort_nums;
for (int i = length; i > pos; i--) {
sort_nums[i] = sort_nums[i - 1];
}
sort_nums[pos] = val;
} else {
sort_nums[length] = val;
}
nums[length] = val;
length++;;
}
void pop() {
if (!isEmpty()) {
int pos = upper_bound(sort_nums, sort_nums + length, nums[length - 1]) - sort_nums;
for (int i = pos - 1; i < length; i++) {
sort_nums[i] = sort_nums[i + 1];
}
} else {
cout << "Invalid" << endl;
return;
}
length--;
cout << nums[length] << endl;
return;
}
void peekMed() {
if (isEmpty()) {
cout << "Invalid" << endl;
} else {
cout << sort_nums[(length - 1) / 2] << endl;
}
}
bool isEmpty() {
return length == 0;
}
} St(100002);
输入数据和问题解决处理
void solve(const string &s) {//根据字符串的第二个字符进行分类操作
if (s[1] == 'u') {
int v;
cin >> v;
St.push(v);
} else if (s[1] == 'o') {
St.pop();
} else {
St.peekMed();
}
}
void Input() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> N;
int n = N;
string s;
while (n--) {
cin >> s;
solve(s);
}
}
整合代码进行提交
应该是最易理解的实现方式了吧!
#include <bits/stdc++.h>
using namespace std;
int N; //输入的操作数
//@实现一个栈,用两个数组实现。
struct Stack {
int *nums; //用作栈空间
int *sort_nums; //将栈元素排序后的情况
int length; //栈的长度
int capcity; //栈的最大容量
Stack(int cap) : nums(nullptr), length(0), capcity(cap), sort_nums(nullptr) {
nums = new int[capcity];
sort_nums = new int[capcity];
}
//@关键在于push和pop操作的处理
void push(int val) {
if (!isEmpty()) {
int pos = upper_bound(sort_nums, sort_nums + length, val) - sort_nums;
for (int i = length; i > pos; i--) {
sort_nums[i] = sort_nums[i - 1];
}
sort_nums[pos] = val;
} else {
sort_nums[length] = val;
}
nums[length] = val;
length++;;
}
void pop() {
if (!isEmpty()) {
int pos = upper_bound(sort_nums, sort_nums + length, nums[length - 1]) - sort_nums;
for (int i = pos - 1; i < length; i++) {
sort_nums[i] = sort_nums[i + 1];
}
} else {
cout << "Invalid" << endl;
return;
}
length--;
cout << nums[length] << endl;
return;
}
void peekMed() {
if (isEmpty()) {
cout << "Invalid" << endl;
} else {
cout << sort_nums[(length - 1) / 2] << endl;
}
}
bool isEmpty() {
return length == 0;
}
} St(100002);
void solve(const string &s) {//根据字符串的第二个字符进行分类操作
if (s[1] == 'u') {
int v;
cin >> v;
St.push(v);
} else if (s[1] == 'o') {
St.pop();
} else {
St.peekMed();
}
}
void Input() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> N;
int n = N;
string s;
while (n--) {
cin >> s;
solve(s);
}
}
int main() {
Input();
return 0;
}