题目
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:
void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
提示:
1 <= x <= 9
- 最多调用
100
次push
、pop
、top
和empty
- 每次调用
pop
和top
都保证栈不为空
进阶:
你能否仅用一个队列来实现栈。
解法1
栈的特点是后入先出(LIFO),队列的特点是先入先出(FIFO),可通过一个队列保存数据,入栈的话直接将数据保存至队列中,但是在出栈的时候,可借助另外一个临时队列先将保存数据队列中除开最后一个数据进行保存,拿到队列中最后一个元素后将剩余元素重复进行保存。
代码如下:
class MyStack {
public:
MyStack() {}
void push(int x) {
data_.push(x);
}
int pop() {
queue<int> buffer{}; // 这里借助另外一个队列保存除开队尾元素的所有元素
while (data_.size() > 1) {
buffer.push(data_.front());
data_.pop();
}
int result = data_.front();
data_.pop();
data_ = std::move(buffer);
return result;
}
int top() {
return data_.back();
}
bool empty() {
return data_.empty();
}
private:
queue<int> data_;
};
执行结果如下:
解法2
在解法1中的pop()
函数借助了另外一个辅助队列来实现,但是队列可以将其转换为一个循环队列,在push(int x)
接口中不断地将新元素移动至队首。
代码如下:
class MyStack {
public:
MyStack() {}
void push(int x) {
size_t size = data_.size();
data_.push(x);
for (size_t i = 0; i < size; ++i) {
data_.push(data_.front());
data_.pop();
}
}
int pop() {
auto result = data_.front();
data_.pop();
return result;
}
int top() {
return data_.front();
}
bool empty() {
return data_.empty();
}
private:
queue<int> data_;
};
执行结果如下:
解法3
和解法2类似,在解法2中通过push(int x)
接口实现一次循环,避免依靠临时队列。那么也可以在pop()
函数中通过对队列做一次循环,同样也避免依赖临时队列。
代码如下:
class MyStack {
public:
MyStack() {}
void push(int x) {
data_.push(x);
}
int pop() {
size_t size = data_.size();
for (size_t i = 0; i < size - 1; ++i) {
data_.push(data_.front());
data_.pop();
}
auto result = data_.front();
data_.pop();
return result;
}
int top() {
return data_.back();
}
bool empty() {
return data_.empty();
}
private:
queue<int> data_;
};
执行结果如下: