栈和队列互相实现
FIFO和FILO,相当于+-号,互转都是利用“负负得正”的原理。
1. 栈实现队列
官方解答中第二种思路很6,按需反转,这样摊还分析下来,复杂度变成了O(1)
class MyQueue {
private:
stack<int> s1;
stack<int> s2;
public:
/** Initialize your data structure here. */
MyQueue() {}
/** Push element x to the back of queue. */
void push(int x) {
s1.push(x);
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
int ret=0;
notempty:
if(!s2.empty()){
ret = s2.top();
s2.pop();
return ret;
}
while(!s1.empty()){
s2.push(s1.top());
s1.pop();
}
//return pop();
goto notempty;
}
/** Get the front element. */
int peek() {
int ret=0;
notempty:
if(!s2.empty()) return s2.top();
while(!s1.empty()){
s2.push(s1.top());
s1.pop();
}
goto notempty;
}
/** Returns whether the queue is empty. */
bool empty() {
return s1.empty() && s2.empty();
}
};
2. 队列实现栈
官方解答中提供了三种思路,我用的方法和方法三很像,又同时做了一点点优化:
- 官方方法三
- 入栈O(N)
- 出栈O(1)
- 我的方法四 (其实思路一样, 就是pop时才去排序.)
- 入栈O(1)
- 出栈O(N),
- 方法四的优化
- 入栈O(1)
- 出栈: 最坏的情况O(N),最好的情况实际pop次数为0
- 缺点: 需要自定义结构体标记
2.1 方法四
class MyStack {
private:
queue<int> buf;
public:
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
buf.push(x);
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int size = buf.size();
int ret = buf.back();
while(--size>=0){
if(size!=0) buf.push(buf.front());
buf.pop();
}
return ret;
}
/** Get the top element. */
int top() {
return buf.back();
}
/** Returns whether the stack is empty. */
bool empty() {
return buf.empty();
}
};
2.2 方法四的优化版
思路就是:
- 用自定义结构体中的flag成员标记当前队列中元素是否有效, 如果是false,则相当于已经被pop(实际并不用pop)
- push直接添加,略
- pop时
- 如果
back().falg==true
,我们直接修改其为false,标记其已经无效了 - 否则,说明倒数两个需要被删除, 按照单队列思路,头循环加到尾部,然后把最后两个都直接pop掉(因为最后一个已经被标记为false,而现在又pop一次,所以两个都直接pop)
- 如果
- top时,类似pop的处理方法
- 最坏的情况:连续pop,但是即使这样pop依然是O(N)
- 最好的情况: push一次,pop一次, 这样实际pop次数为0
- 混合情况: 优于单队列
typedef struct {
int val;
bool flag;
}myint;
class MyStack {
private:
queue<myint> buf;
public:
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
myint mx = {x, true};
buf.push(mx);
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
if(buf.back().flag == true) {
buf.back().flag=false;
return buf.back().val;
}
int size = buf.size();
while(--size>=2){
buf.push(buf.front());
buf.pop();
}
int ret = buf.front().val;
buf.pop();
buf.pop();
return ret;
}
/** Get the top element. */
int top() {
if(buf.back().flag==true) return buf.back().val;
int size = buf.size();
while(--size>=1){
buf.push(buf.front());
buf.pop();
}
buf.pop();
return buf.back().val;
}
/** Returns whether the stack is empty. */
bool empty() {
return (buf.empty() || (!buf.front().flag));
}
};