← All Guides

Stacks & Queues

9 drills · 9 pattern exercises · 11 micro drills

Patterns Overview

Patterns used in this topic, with difficulty breakdown.

Stack Matching 1 drill 1 Med
Lazy Transfer 1 drill 1 Med
Pair with Min 1 drill 1 Med
Operand Stack 1 drill 1 Easy
Monotonic Stack 2 drills 2 Med
Index Stack 1 drill 1 Easy
Push/Pop All 1 drill 1 Easy
Stack Eval 1 drill 1 Med

Foundation Drill

19 Evaluate postfix expression Easy Operand Stack

Calculate the result of a math expression written in postfix notation like '2 1 + 3 *'.

Start here in Foundations →

Coding Drills

All 9 drills grouped by pattern. Each includes prompt, solution, and complexity.

Stack Matching (1)

16 Balanced brackets Medium

In plain English: Check if every opening bracket has a matching closing bracket in the correct order.

A stack naturally models nesting: the most recent opening bracket must match the next closing bracket — LIFO order.

Prompt

Check if a string of brackets is balanced: ()[]{}

Solution

def is_balanced(s):
    stack = []
    pairs = {')':'(', ']':'[', '}':'{'}
    for c in s:
        if c in '([{':
            stack.append(c)
        # LIFO matches innermost first
        elif c in pairs:
            if not stack or stack.pop() != pairs[c]:
                return False
    return len(stack) == 0

# Test: is_balanced("{[()]}") == True
# Test: is_balanced("{[(])}") == False
O(n) time · O(n) space

Lazy Transfer (1)

17 Queue using two stacks Medium

In plain English: Build a first-in-first-out queue using only two last-in-first-out stacks.

Reversing a stack flips LIFO into FIFO — the lazy transfer (only when output is empty) makes this amortized O(1).

Prompt

Implement a FIFO queue using only two stacks.

Solution

class Queue:
    def __init__(self):
        self.sin = []
        self.sout = []
    def enqueue(self, x):
        self.sin.append(x)
    def dequeue(self):
        if not self.sout:
            # lazy transfer: only when needed
            while self.sin:
                self.sout.append(self.sin.pop())
        return self.sout.pop()

# Test: q = Queue(); q.enqueue(1); q.enqueue(2); q.dequeue() == 1
O(1) amortized per operation

Pair with Min (1)

18 Min stack Medium

In plain English: Build a stack that also tells you the current minimum element in O(1) time.

Storing the running minimum alongside each value preserves the min history as elements are popped — no need to rescan.

Prompt

Design a stack that supports push, pop, and getMin in O(1).

Solution

class MinStack:
    def __init__(self):
        self.stack = []  # stores (val, cur_min)
    def push(self, x):
        cur_min = min(x, self.stack[-1][1]) if self.stack else x
        self.stack.append((x, cur_min))  # pair: (value, min-so-far)
    def pop(self):
        return self.stack.pop()[0]
    def get_min(self):
        return self.stack[-1][1]

# Test: push(3), push(1), push(5) => get_min() == 1
O(1) all operations · O(n) space

Operand Stack (1)

19 Evaluate postfix expression Easy

In plain English: Calculate the result of a math expression written in postfix notation like '2 1 + 3 *'.

Postfix notation eliminates the need for parentheses and precedence — operands are always ready on the stack when an operator appears.

Prompt

Evaluate a postfix (reverse Polish notation) expression.

Solution

def eval_postfix(tokens):
    stack = []
    ops = {'+': lambda a,b: a+b, '-': lambda a,b: a-b,
           '*': lambda a,b: a*b, '/': lambda a,b: int(a/b)}
    for t in tokens:
        if t in ops:
            b, a = stack.pop(), stack.pop()  # pop order matters: b first, then a
            stack.append(ops[t](a, b))
        else:
            stack.append(int(t))
    return stack[0]

# Test: eval_postfix(["2","1","+","3","*"]) == 9
O(n) time · O(n) space

Monotonic Stack (2)

20 Next greater element Medium

In plain English: For each number in an array, find the first larger number to its right.

A monotonic stack maintains elements in decreasing order — when a larger element arrives, it 'resolves' all smaller elements on the stack.

Prompt

For each element, find the next element to its right that is larger.

Solution

def next_greater(a):
    res = [-1] * len(a)
    stack = []
    for i in range(len(a) - 1, -1, -1):
        while stack and stack[-1] <= a[i]:  # pop smaller elements: they found their answer
            stack.pop()
        if stack:
            res[i] = stack[-1]
        stack.append(a[i])
    return res

# Test: next_greater([4,5,2,25]) == [5,25,25,-1]
O(n) time · O(n) space
135 Daily Temperatures Medium

In plain English: For each day, find how many days you have to wait until a warmer day comes.

Use a monotonic decreasing stack of indices. When a new temperature is higher than the stack top, pop and record the distance. Each element is pushed and popped at most once — O(n) total.

Prompt

Given an array of daily temperatures, return an array where each element says how many days until a warmer temperature. If none, put 0.

Solution

def daily_temperatures(temps):
    n = len(temps)
    result = [0] * n
    stack = []  # monotonic decreasing stack of indices
    for i in range(n):
        while stack and temps[i] > temps[stack[-1]]:
            j = stack.pop()
            result[j] = i - j
        stack.append(i)
    return result

# Test: daily_temperatures([73,74,75,71,69,72,76,73])
#       == [1,1,4,2,1,1,0,0]
O(n) time · O(n) space

Index Stack (1)

21 Valid parentheses string Easy

In plain English: Check if a string of parentheses is properly opened and closed.

Every open paren expects exactly one close paren — the stack tracks unmatched opens and must be empty at the end.

Prompt

Check if a string of parentheses () is valid.

Solution

def is_valid(s):
    stack = []  # track unmatched open parens
    for c in s:
        if c == '(':
            stack.append(c)
        elif c == ')':
            if not stack:
                return False  # no matching open
            stack.pop()
    return len(stack) == 0  # all opens must be matched

# Test: is_valid("(())()") == True
# Test: is_valid("(()") == False
O(n) time · O(n) space

Push/Pop All (1)

22 Reverse string with stack Easy

In plain English: Reverse a string by pushing all characters onto a stack and popping them off.

LIFO order naturally reverses a sequence — push in order, pop gives reverse order.

Prompt

Reverse a string using a stack.

Solution

def reverse_string(s):
    stack = list(s)  # push all chars
    result = []
    while stack:
        result.append(stack.pop())  # LIFO pops in reverse order
    return ''.join(result)

# Test: reverse_string("hello") == "olleh" 
O(n) time · O(n) space

Stack Eval (1)

134 Evaluate Reverse Polish Notation Medium

In plain English: Evaluate a math expression written in postfix notation using a stack.

Push numbers onto the stack. When you hit an operator, pop two operands, apply the operator, and push the result. The stack naturally handles operator precedence and nesting.

Prompt

Evaluate an expression in Reverse Polish Notation (postfix). Valid operators are +, -, *, /. Each operand is an integer.

Solution

def eval_rpn(tokens):
    stack = []
    ops = {
        '+': lambda a, b: a + b,
        '-': lambda a, b: a - b,
        '*': lambda a, b: a * b,
        '/': lambda a, b: int(a / b),  # truncate toward zero
    }
    for t in tokens:
        if t in ops:
            b, a = stack.pop(), stack.pop()
            stack.append(ops[t](a, b))
        else:
            stack.append(int(t))
    return stack[0]

# Test: eval_rpn(["2","1","+","3","*"]) == 9  ((2+1)*3)
# Test: eval_rpn(["4","13","5","/","+"]) == 6  (4+(13/5))
O(n) time · O(n) space

Pattern Recognition

9 exercises: spot the signals, pick the method, avoid the trap.

16 Balanced brackets Medium

Check if a string of brackets is balanced: ()[]{}

Signals

Stack

Push open brackets, pop on close brackets. Top must match. Stack empty at end → balanced. O(n).

Trap

Counter-based approach only works for single bracket type. Multiple types require a stack.

17 Queue using two stacks Medium

Implement a FIFO queue using only two stacks.

Signals

Stack

Push to inbox stack. On dequeue, transfer inbox → outbox (reversal). Amortized O(1) per operation.

Trap

Only transfer to outbox when outbox is empty — transferring every time is O(n) per dequeue.

18 Min stack Medium

Design a stack that supports push, pop, and getMin in O(1).

Signals

Stack

Store (value, current_min) pairs. On push, new_min = min(val, top.min). O(1) for all operations.

Trap

Tracking a single min variable breaks on pop — you lose the previous minimum.

19 Evaluate postfix expression Easy

Evaluate a postfix (reverse Polish notation) expression.

Signals

Stack

Push numbers. On operator, pop two, apply, push result. Final stack element is the answer. O(n).

Trap

Watch operand order for non-commutative ops: second_popped OP first_popped (e.g., subtraction).

20 Next greater element Medium

For each element, find the next element to its right that is larger.

Signals

Monotonic Stack

Maintain decreasing stack of indices. When a larger element arrives, it's the answer for all smaller stack elements. O(n).

Trap

Brute force nested loop is O(n²). The monotonic stack insight gives O(n) because each element is pushed/popped at most once.

21 Valid parentheses string Easy

Check if a string of parentheses () is valid.

Signals

Stack

Push '(' on open, pop on ')'. If stack empty when popping or non-empty at end → invalid. O(n).

Trap

A simple counter (increment on open, decrement on close) works here but doesn't extend to mixed bracket types.

22 Reverse string with stack Easy

Reverse a string using a stack.

Signals

Stack

Push each character, pop all into result. LIFO reverses the order. O(n).

Two Pointers

In-place swap from both ends — more efficient (O(1) space) but the problem specifically asks for stack.

Trap

The problem constraints dictate the method here — 'using a stack' means use a stack.

134 Evaluate Reverse Polish Notation Medium

Evaluate an arithmetic expression in Reverse Polish Notation (postfix).

Signals

Stack

Push numbers. On operator, pop two, compute, push result. O(n).

Trap

Division truncates toward zero in RPN. In Python, use int(a/b) not a//b (which floors).

135 Daily Temperatures Medium

Given daily temperatures, for each day find how many days until a warmer temperature.

Signals

Monotonic Stack

Decreasing stack of indices. Pop while current temp > stack top. Distance = current - popped index. O(n).

Stack

Same approach. Each element pushed and popped at most once.

Trap

Don't scan forward from each day — that's O(n²). The monotonic stack makes it one pass.

Related Micro Drills

11 quick recall drills to reinforce this topic.

35 Check balanced parens Stack Discipline 15s

Bracket matching is the classic stack application. Must be instant for interview warm-ups.

match = {'(': ')', '[': ']', '{': '}'}
stack = []
for c in s:
    if c in match:
        stack.append(match[c])
    elif not stack or stack.pop() != c:
        return False
return not stack
34 Push and pop Stack Discipline 5s

Stack push/pop is the foundation for all LIFO operations: DFS, undo, and expression parsing.

stack = []
stack.append(x)
stack.pop()
38 Monotonic stack template Stack Discipline 10s

Monotonic stacks find next-greater/smaller elements in O(n). Key for histogram and temperature problems.

stack = []
for x in a:
    while stack and stack[-1] >= x:
        stack.pop()
    stack.append(x)
45 Queue from two stacks idea Queue Patterns 15s

Two-stack queue amortizes to O(1) per operation. Classic data structure design question.

in_stack, out_stack = [], []

def enqueue(x):
    in_stack.append(x)

def dequeue():
    if not out_stack:
        while in_stack:
            out_stack.append(in_stack.pop())
    return out_stack.pop()
36 Min stack push Stack Discipline 10s

Maintaining a parallel min stack gives O(1) getMin. Classic design problem.

self.stack.append(val)
self.min_stack.append(
    min(val, self.min_stack[-1] if self.min_stack else val)
)
40 Stack to reverse Stack Discipline 10s

Using a stack to reverse order is the intuition behind reversing linked lists and strings.

stack = []
for x in a:
    stack.append(x)
reversed_a = []
while stack:
    reversed_a.append(stack.pop())
37 Evaluate postfix token Stack Discipline 15s

Stack-based expression evaluation is the foundation for calculator and RPN problems.

for tok in tokens:
    if tok.lstrip('-').isdigit():
        stack.append(int(tok))
    else:
        b, a = stack.pop(), stack.pop()
        if tok == '+': stack.append(a + b)
        elif tok == '-': stack.append(a - b)
        elif tok == '*': stack.append(a * b)
        elif tok == '/': stack.append(int(a / b))
272 Evaluate Reverse Polish Notation Stack Discipline 15s

RPN evaluation: numbers push, operators pop two and push result. Note: pop order is b, a (right operand first).

stack = []
for tok in tokens:
    if tok in '+-*/':
        b, a = stack.pop(), stack.pop()
        if tok == '+': stack.append(a + b)
        elif tok == '-': stack.append(a - b)
        elif tok == '*': stack.append(a * b)
        else: stack.append(int(a / b))
    else:
        stack.append(int(tok))
39 Next greater element Stack Discipline 15s

Next-greater-element uses a decreasing stack. Shows up in stock span and temperature problems.

result = [-1] * len(a)
stack = []
for i in range(len(a) - 1, -1, -1):
    while stack and stack[-1] <= a[i]:
        stack.pop()
    if stack:
        result[i] = stack[-1]
    stack.append(a[i])
136 Generate parentheses backtrack Recursion & DP 15s

Track open/close counts. Only add close paren when close < open.

def bt(o, c, cur):
    if len(cur) == 2*n: res.append(cur); return
    if o &lt; n: bt(o+1, c, cur+'(')
    if c &lt; o: bt(o, c+1, cur+')')
135 Daily temperatures monotonic stack Stack Discipline 15s

Decreasing stack resolves waiting days when a warmer temperature arrives.

res = [0] * len(t)
st = []
for i, v in enumerate(t):
    while st and t[st[-1]] &lt; v:
        j = st.pop()
        res[j] = i - j
    st.append(i)