Topics
We use two queues:
- An active queue (our main storage)
q2
- A temporary queue (our rearrangement assistant)
q1
Push Operation:
- When a new element arrives, it starts in the temporary queue, i.e.
q1.push(x)
- We then transfer ALL existing elements from the active queue to the temporary queue, i.e.
move_from_q2_to_q1()
. This crucial step places the new element at the front, with all previous elements following it - We then
swap(q1, q2)
, making the temporary queue our new active queue- This way, the last added element always stays at the front of the active queue, ensuring the correct behavior forĀ
pop
Ā andĀtop
- This way, the last added element always stays at the front of the active queue, ensuring the correct behavior forĀ
Note
The invariants here is that the temporary queue is always empty for new element to arrive, while the active queue always maintains elements in LIFO order.
class Solution {
public:
// q1: temporary queue, q2: active queue
queue<int> q1, q2;
Solution() {}
void move_from_q2_to_q1() {
while (!q2.empty()) {
q1.push(q2.front());
q2.pop();
}
}
void push(int x) {
q1.push(x);
move_from_q2_to_q1();
// always make sure q1 points to empty queue
swap(q1, q2);
}
int pop() {
if (q2.empty())
return -1;
int val = q2.front();
q2.pop();
return val;
}
int top() {
if (q2.empty())
return -1;
return q2.front();
}
bool empty() { return q2.empty(); }
};
Time Complexity
- Push: (since
move_from_q2_to_q1
transfers elements in linear time) - Pop and Top:
Space Complexity