Implement Stack Using Queue in DSA Python - Time & Space Complexity
We want to understand how long it takes to perform stack operations when using a queue to build it.
Specifically, how does the time grow as we add more items?
Analyze the time complexity of the following code snippet.
class StackUsingQueue:
def __init__(self):
self.q = []
def push(self, x):
self.q.append(x)
for _ in range(len(self.q) - 1):
self.q.append(self.q.pop(0))
def pop(self):
return self.q.pop(0) if self.q else None
def top(self):
return self.q[0] if self.q else None
def empty(self):
return len(self.q) == 0
This code uses one queue to simulate a stack. The push operation rotates the queue to keep the newest element at the front.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The for-loop inside the push method that moves elements from front to back.
- How many times: It runs (n-1) times where n is the current number of elements in the queue.
Each push moves almost all existing elements to the back of the queue to keep the newest element at front.
| Input Size (n) | Approx. Operations in push |
|---|---|
| 10 | 9 moves |
| 100 | 99 moves |
| 1000 | 999 moves |
Pattern observation: The number of moves grows linearly as the stack grows.
Time Complexity: O(n)
This means pushing an item takes longer as the stack gets bigger, roughly proportional to the number of items.
[X] Wrong: "Push operation is always O(1) because we just add one item to the queue."
[OK] Correct: Because after adding, we rotate all other items to keep stack order, which takes O(n) time.
Understanding how to build one data structure using another and analyzing its time helps you think flexibly and solve problems creatively.
"What if we used two queues instead of one? How would the time complexity of push and pop change?"
Practice
Solution
Step 1: Understand stack and queue differences
A stack follows Last-In-First-Out (LIFO), while a queue follows First-In-First-Out (FIFO).Step 2: Simulate stack using queue(s)
By using one or two queues cleverly, we can reorder elements to behave like a stack for push and pop operations.Final Answer:
Use one or two queues to simulate stack operations like push and pop -> Option CQuick Check:
Stack via queue = simulate push/pop [OK]
- Confusing stack and queue order
- Trying to sort queue instead of simulating stack
- Using stack to implement queue instead
Solution
Step 1: Recall Python queue initialization
collections.deque() is the correct way to create a double-ended queue in Python.Step 2: Check options
Only queue = deque() uses deque() correctly; others are either list or undefined.Final Answer:
queue = deque() -> Option AQuick Check:
collections.deque() creates queue [OK]
- Using list [] instead of deque
- Calling undefined Queue() class
- Using lowercase queue() which is not defined
from collections import deque
class Stack:
def __init__(self):
self.q = deque()
def push(self, x):
self.q.append(x)
for _ in range(len(self.q) - 1):
self.q.append(self.q.popleft())
def pop(self):
return self.q.popleft() if self.q else None
s = Stack()
s.push(10)
s.push(20)
s.push(30)
print(s.pop())
print(s.pop())
print(s.pop())Solution
Step 1: Understand push operation
Push appends element then rotates queue so new element is at front.Step 2: Trace push and pop calls
Push 10: queue=[10]
Push 20: queue=[20,10]
Push 30: queue=[30,20,10]
Pop removes front: 30, then 20, then 10.Final Answer:
30 20 10 -> Option DQuick Check:
Stack pop order = 30,20,10 [OK]
- Ignoring rotation in push
- Assuming pop removes last element instead of front
- Confusing queue order with stack order
from collections import deque
class Stack:
def __init__(self):
self.q1 = deque()
self.q2 = deque()
def push(self, x):
self.q1.append(x)
def pop(self):
while len(self.q1) > 1:
self.q2.append(self.q1.popleft())
return self.q1.popleft()
self.q1, self.q2 = self.q2, self.q1
Solution
Step 1: Analyze pop method flow
Pop moves all but last from q1 to q2, then pops last from q1.Step 2: Identify missing swap
After popping, q1 is empty but queues are not swapped, so next push/pop fail.Final Answer:
The queues are not swapped after pop, so q1 becomes empty -> Option AQuick Check:
Missing swap causes empty q1 [OK]
- Not swapping queues after pop
- Returning before swapping queues
- Appending to wrong queue in push
push operation to maintain stack order?Solution
Step 1: Understand stack order with one queue
To simulate LIFO, after adding new element, rotate queue so new element is front.Step 2: Compare approaches
Append the new element, then rotate the queue by dequeuing and enqueuing all previous elements rotates queue after append, maintaining stack order. Append the new element and do nothing else does not reorder. Dequeue all elements, enqueue the new element, then enqueue all dequeued elements is inefficient but correct logically. Use two queues to enqueue the new element in the empty queue uses two queues, not single.Final Answer:
Append the new element, then rotate the queue by dequeuing and enqueuing all previous elements -> Option BQuick Check:
Rotate after push keeps stack order [OK]
- Not rotating queue after push
- Using two queues when only one is allowed
- Appending without reordering elements
Ready to prove it?
Pass the test and this pattern moves unknown
