原题
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
示例 1:
输入:
[“CQueue”,“appendTail”,“deleteHead”,“deleteHead”]
[[],[3],[],[]]
输出:[null,null,3,-1]示例 2:
输入:
[“CQueue”,“deleteHead”,“appendTail”,“appendTail”,“deleteHead”,“deleteHead”]
[[],[],[5],[2],[],[]]
输出:[null,-1,null,null,5,2]提示:
1 <= values <= 10000
最多会对 appendTail、deleteHead 进行 10000 次调用来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof
思路
Ⅰ. 知识回顾
- 栈,先进后出,我们不能直接操作栈底元素,只能
- 队列,先进先出。
Ⅱ. 题目分析
我们设计两个栈,把其中一个栈的元素依次压出第二个栈,再把第二个栈的内容依次压入第一个栈,由于栈的“先进后出”性质,这时我们按照栈的方法操作第一个栈,就可以实现队列的“先进先出”功能了。
步骤
- 在插入元素方法中
- 如果,第一个栈不为空,把第一个栈的所有元素压入第二个栈
- 在第一个栈插入元素
- 如果第二个栈不为空,把第二个栈的所有元素压入第一个栈
- 删除元素方法中
- 因为第一个栈的元素已经是按照队列的“先进先出”存储好了,所以直接操作第一个栈即可。
代码
- c++代码
class CQueue {
private:
stack<int> s1;
stack<int> s2;
public:
CQueue() {
}
void appendTail(int value) {
while (!s1.empty()) {
s2.push(s1.top());
s1.pop();
}
s1.push(value);
while (!s2.empty()) {
s1.push(s2.top());
s2.pop();
}
}
int deleteHead() {
if (s1.empty()) {
return -1;
}
int ret = s1.top();
s1.pop();
return ret;
}
};
/**
* Your CQueue object will be instantiated and called as such:
* CQueue* obj = new CQueue();
* obj->appendTail(value);
* int param_2 = obj->deleteHead();
*/
- python代码
class CQueue:
def __init__(self):
self.s1, self.s2 = [], []
def appendTail(self, value: int) -> None:
while self.s1:
self.s2.append(self.s1.pop())
self.s1.append(value);
while self.s2:
self.s1.append(self.s2.pop())
def deleteHead(self) -> int:
if not self.s1:
return -1
return self.s1.pop()
# Your CQueue object will be instantiated and called as such:
# obj = CQueue()
# obj.appendTail(value)
# param_2 = obj.deleteHead()
复杂度分析
插入元素
- 时间复杂度 O ( N ) O(N) O(N),插入元素时,对于已有元素,每个元素都要弹出栈两次,压入栈两次。
- 空间复杂度 O ( N ) O(N) O(N), 需要使用额外空间。
删除元素
- 时间复杂度 O ( 1 ) O(1) O(1)
- 空间复杂度 O ( 1 ) O(1) O(1)
Ⅲ. 优化
上面的代码尽管插入元素的时间复杂度已经是 O ( N ) O(N) O(N)了,但是跑起来的效率相对比较慢。
通过分析我们知道,每次我们插入元素的时候,都要把栈1的所有元素都压入栈2,再把栈2的元素压入栈1,能不能优化下。
具体问题具体分析,结果不是最优,肯定还有好的方法。
- c++代码
class CQueue {
private:
stack<int> s1, s2;
public:
CQueue() {
}
void appendTail(int value) {
s1.push(value);
}
int deleteHead() {
if (s1.empty() && s2.empty()) {
return -1;
} else if (s2.empty() && !s1.empty()) {
while (!s1.empty()) {
s2.push(s1.top());
s1.pop();
}
}
int ret = s2.top();
s2.pop();
return ret;
}
};
/**
* Your CQueue object will be instantiated and called as such:
* CQueue* obj = new CQueue();
* obj->appendTail(value);
* int param_2 = obj->deleteHead();
*/
- python代码
class CQueue:
def __init__(self):
self.s1, self.s2 = [], []
def appendTail(self, value: int) -> None:
self.s1.append(value)
def deleteHead(self) -> int:
if not self.s1 and not self.s2:
return -1
elif self.s1 and not self.s2:
while self.s1:
self.s2.append(self.s1.pop())
return self.s2.pop()
# Your CQueue object will be instantiated and called as such:
# obj = CQueue()
# obj.appendTail(value)
# param_2 = obj.deleteHead()