题目描述:
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
说明:
你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
题目解答:
class MyQueue {
public:stack<int> s_input,s_output;MyQueue() {}void push(int x) {s_input.push(x);}int pop() {if(s_output.empty()){while(!s_input.empty()){s_output.push(s_input.top());s_input.pop();}}int res=s_output.top();s_output.pop();return res;}int peek() {int res=this->pop();s_output.push(res);return res;}bool empty() {return s_input.empty() && s_output.empty();}
};/*** Your MyQueue object will be instantiated and called as such:* MyQueue* obj = new MyQueue();* obj->push(x);* int param_2 = obj->pop();* int param_3 = obj->peek();* bool param_4 = obj->empty();*/
题目思路:
优化后的代码思路主要集中在减少不必要的元素移动操作,特别是在pop
和peek
方法中。这里我们详细分析优化后的代码思路:
成员变量
代码中有两个栈:s_input
和s_output
。s_input
用于接收所有入队的元素,而s_output
用于辅助实现队列的先进先出特性。
方法
1. push(int x)
当元素入队时,直接将其压入s_input
栈。这是队列的基本入队操作,没有变化。
2. pop()
在出队操作时,首先检查s_output
栈是否为空。如果为空,意味着所有入队的元素都还在s_input
中,且尚未以队列的顺序排列。此时,需要将s_input
中的所有元素逐一弹出并压入s_output
,这样s_output
的栈顶元素就是队列的队首元素。完成这个步骤后,s_output
的栈顶元素就可以安全地弹出并返回。
优化点:通过确保在每次pop
之前s_output
中都有元素(除非队列本身为空),我们可以避免在每次pop
时都检查并移动元素。这提高了效率,因为一旦s_output
被填充,后续的pop
操作就可以直接从s_output
中执行,而无需再次移动元素。
3. peek()
peek
方法用于查看队列的队首元素但不移除它。其逻辑与pop
方法类似,首先检查s_output
是否为空。如果为空,则将s_input
中的元素移动到s_output
。然后,返回s_output
的栈顶元素,但不弹出它。
优化点:与pop
方法共享相同的逻辑来确保s_output
中有元素,避免了重复的检查和移动操作。这提高了peek
方法的效率。
4. empty()
这个方法检查队列是否为空。它通过检查s_input
和s_output
两个栈是否都为空来实现。如果两个栈都为空,则队列为空。
总结
主要是利用两个栈来实现队列的功能,并通过确保s_output
栈在pop
和peek
操作前总是包含队列的元素(除非队列为空),来减少不必要的元素移动。这种优化减少了重复操作,提高了队列操作的效率。