Don't use a list as a queue — list.pop(0) is O(n) because it shifts every element. Always use deque.
Balanced Brackets — Classic Stack Problem
defis_balanced(s: str) -> bool:
stack, pairs = [], {')':'(', ']':'[', '}':'{'}
for ch in s:
if ch in'([{': stack.append(ch)
elif ch in pairs:
if not stack or stack[-1] != pairs[ch]: returnFalse
stack.pop()
return not stack
print(is_balanced("({[]})")) # Trueprint(is_balanced("({)}")) # False
Practice
1. Why does using a list for a queue give O(n) dequeue?
list.pop(0) removes the first element, then shifts every remaining element
one position left — O(n) work. deque stores elements as a doubly-linked
list of fixed-size blocks, so popleft() is O(1).
2. Implement a function using two stacks to simulate a queue.
class TwoStackQueue:
def __init__(self): self.inbox, self.outbox = [], []
def enqueue(self, v): self.inbox.append(v)
def dequeue(self):
if not self.outbox:
while self.inbox: self.outbox.append(self.inbox.pop())
return self.outbox.pop()
Knowledge Check
Stack operations push and pop are
Correct — append/pop from the end of a list are constant time.
Shifting is not needed; stack operates at one end only.
No searching or tree traversal involved.
That's a typical sorting bound.
Recap: stack push = list.append (O(1)). Stack pop = list.pop() from end (O(1)). No shifting needed.
Which Python collection provides O(1) popleft()?
list.pop(0) is O(n) — all elements shift.
Correct — deque is a double-ended queue; both ends are O(1).
Sets are unordered; no popleft concept.
Tuples are immutable.
Recap: always use collections.deque for queues. list is fine for stacks (operate only at one end).
The call stack in a program uses which data structure?
Queues are FIFO; function calls use LIFO (most-recent first).
Correct — each function call pushes a frame; returning pops it.
The heap is for dynamic memory allocation, not call tracking.
Conceptually it's a stack, not a linked list.
Recap: the 'call stack' is literally a stack. Each function invocation pushes an activation record; each return pops it.
is_balanced works by
Counting alone fails for interleaved types like ({)}.
Correct — the top of the stack must match the current closer.
Sorting destroys order information.
The iterative stack approach is standard.
Recap: push open brackets; when you see a close bracket, check if the top matches. At the end, the stack must be empty.
A queue is appropriate when
LIFO is a stack.
Correct — print queues, BFS, CPU scheduling all use FIFO.
Neither stack nor queue supports O(1) random access.
Sorted access needs a priority queue (heap), not a plain queue.
Recap: queue = FIFO. Stack = LIFO. Choose based on whether you need to process in arrival order or reverse order.