DSA · Topic 4 of 18 · Core Structures

Stack

The most recent unfinished thing comes first: push it, and pop when its match arrives.

6 problems · O(n): each item is pushed and popped at most once time, O(n) space

Step 1 Understand it

Remember it by

The most recent unfinished thing comes first: push it, and pop when its match arrives.

Watch it happen

AnimationA stack: the most recent unfinished thing is resolved first
Read the animation as text
  1. Every closing bracket must match the most recent opening bracket that is still open. "Most recent first" is exactly what a stack gives you.
  2. '(' opens something: push it on the stack. It waits for its match.
  3. '[' opens something: push it on the stack. It waits for its match.
  4. ']' closes something. The top of the stack is '[' — a match, so pop it.
  5. '{' opens something: push it on the stack. It waits for its match.
  6. '}' closes something. The top of the stack is '{' — a match, so pop it.
  7. ')' closes something. The top of the stack is '(' — a match, so pop it.
  8. End of the string and the stack is empty: every bracket was matched in the right order. Answer: True. (A leftover item, or a mismatch on top, would mean False.)

The idea

A stack is last-in, first-out. Use it when the newest item is the one that gets resolved next: matching brackets, undo, or 'the next greater element' (a monotonic stack keeps items in sorted order and pops everything the new item beats).

Picture it

flowchart LR
  N["next value x"] --> Q{"stack not empty and<br/>top value < x?"}
  Q -->|"yes"| P["pop the top:<br/>its answer is x"] --> Q
  Q -->|"no"| PU["push x"] --> N
A monotonic stack: everything x beats is popped and answered; then x waits on the stack for its own answer.

Analogy

A pile of plates: you add and remove only from the top. For brackets, every closing one must match the plate on top.

Where the analogy breaks

Plates don't care about order. A monotonic stack does: before pushing, it pops every item smaller (or bigger) than the new one, and that pop is the moment you record an answer.

More detail

What it is

Imagine a stack of dinner plates. You can only put a new plate on the very top, and when you need a plate, you can only grab the one from the very top. You can't magically pull one from the middle! This is a Stack data structure. It operates strictly on the Last-In, First-Out (LIFO) principle. Whatever goes in last is the absolute first thing that comes out.

When to use it

  • When you need to remember previous states and return to them in reverse order.
  • When parsing brackets, tags, or mathematical expressions (like ([{ }])).
  • When dealing with 'Next Greater Element' or 'Previous Smaller Element' problems.
  • When implementing Undo features or browsing history.

How it works

You create a Stack (often just a dynamic array or built-in Stack class). You push() elements onto the top of the stack as you process them. When you need to backtrack or match a previous element, you pop() from the top. You can also peek() to just look at the top element without removing it.

Example walkthrough

Input: s = "()[]{}"

  1. See '('. It's an opening bracket, push to stack.
  2. See ')'. It's closing. Does it match the top of the stack '('? Yes! Pop it.
  3. See '['. Push.
  4. See ']'. Matches top. Pop.
  5. See '{'. Push.
  6. See '}'. Matches top. Pop. Stack is empty, so it's valid!

Result: true

Related patterns

  • Monotonic Stack: A special stack where elements are forced to be entirely increasing or decreasing. Extremely useful for 'Next Greater Element' problems.

Step 2 Recognise it

Words that signal it

  • 'Valid parentheses', nested or matching pairs
  • 'Next greater / smaller element', 'how many days until warmer'
  • 'Evaluate an expression', 'decode a string'
  • 'Undo', 'backspace', 'most recent'

Don't confuse it with

  • Queue / BFS: First-in, first-out (process in arrival order, level by level) → queue. Most recent first → stack.
  • Two Pointers: A palindrome check uses two pointers; nested matching (brackets) needs a stack because pairs can wrap around each other.

Gut check

Does the newest item get resolved first, or do I need the next bigger thing? → stack.

How to recognise it in an interview

The problem involves 'matching' elements, 'nearest', 'undo', or checking if things are 'validly nested'.

Step 3 The template

The general shape. Adapt it to each problem rather than learning one solution per problem.

python
def next_greater(nums):
    answer = [-1] * len(nums)
    stack = []                          # indexes; their values are decreasing
    for i, x in enumerate(nums):
        while stack and nums[stack[-1]] < x:
            j = stack.pop()             # x is the first thing bigger than nums[j]
            answer[j] = x               # (or i - j for a distance)
        stack.append(i)
    return answer
The same template in Java
text
class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        for (char c : s.toCharArray()) {
            if (c == '(' || c == '{' || c == '[') {
                stack.push(c);
            } else {
                if (stack.isEmpty()) return false;
                char top = stack.pop();
                if (c == ')' && top != '(') return false;
                if (c == '}' && top != '{') return false;
                if (c == ']' && top != '[') return false;
            }
        }
        return stack.isEmpty();
    }
}
TimeO(n): each item is pushed and popped at most once
SpaceO(n)

Common mistakes

  • Popping from an empty stack: check if stack before stack[-1].
  • Forgetting the leftovers at the end: in Valid Parentheses, a non-empty stack means unmatched openers.
  • Storing values when you need distances: push indexes, then i − j gives the gap (Daily Temperatures).

Step 4 Watch it run

Two problems, traced step by step exactly as the code runs.

Easy example: Valid Parentheses

Input: s = '([]{})'

charactionstack after
(opening → push(
[opening → push([
]matches top '[' → pop(
{opening → push({
}matches top '{' → pop(
)matches top '(' → popempty

Result: True

Notice: A closing bracket must match the most recent unmatched opener — exactly what the top of the stack is.

python
def is_valid(s):
    pairs = {')': '(', ']': '[', '}': '{'}
    stack = []
    for ch in s:
        if ch in pairs:
            if not stack or stack[-1] != pairs[ch]:
                return False
            stack.pop()
        else:
            stack.append(ch)
    return not stack

Medium example: Daily Temperatures

Input: temperatures = [73, 74, 75, 71, 69, 72, 76, 73]

day (temp)popped (answered)stack after: day(temp)
0 (73)nothing warmer to resolve0(73)
1 (74)day 0 (73) waits 11(74)
2 (75)day 1 (74) waits 12(75)
3 (71)nothing warmer to resolve2(75), 3(71)
4 (69)nothing warmer to resolve2(75), 3(71), 4(69)
5 (72)day 4 (69) waits 1; day 3 (71) waits 22(75), 5(72)
6 (76)day 5 (72) waits 1; day 2 (75) waits 46(76)
7 (73)nothing warmer to resolve6(76), 7(73)

Result: [1, 1, 4, 2, 1, 1, 0, 0]

Notice: Days wait on the stack until a warmer day arrives. Each day is pushed once and popped once, so it's O(n), not O(n²).

python
def daily_temperatures(temps):
    answer = [0] * len(temps)
    stack = []                          # days still waiting for a warmer day
    for i, t in enumerate(temps):
        while stack and temps[stack[-1]] < t:
            j = stack.pop()
            answer[j] = i - j
        stack.append(i)
    return answer

Step 5 Practise

Read each question and say the pattern and the trick out loud before you open the answer. Then solve it on LeetCode. Tick a problem once you've solved it on your own: it comes back for review tomorrow, then after 3, 7, 14 and 30 days, then every month, on the DSA page.

Easy

  1. Valid Parentheses Easy

    Decide whether a string of brackets is correctly opened and closed.

    Show answer

    Technique: Stack

    The clue: Nested matching pairs.

    The trick: Push openers; each closer must match the top of the stack; the stack must end empty.

Medium

  1. Min Stack Medium

    Design a stack that also returns its minimum in O(1).

    Show answer

    Technique: Stack with a second 'minimum so far' stack

    The clue: O(1) minimum while items come and go in stack order.

    The trick: Alongside each pushed value, push the minimum so far; popping removes both.

  2. Evaluate Reverse Polish Notation Medium

    Evaluate an expression written in reverse Polish notation, like ['2', '1', '+', '3', '*'].

    Show answer

    Technique: Stack

    The clue: Each operator uses the two most recent numbers.

    The trick: Push numbers; on an operator, pop two (b first, then a), push a op b; divide truncating towards zero.

  3. Daily Temperatures Medium

    For each day, how many days until a warmer temperature?

    Show answer

    Technique: Monotonic decreasing stack

    The clue: 'How long until the next greater…'.

    The trick: Keep waiting days on a stack; a warmer day pops and answers all cooler days on top.

  4. Car Fleet Medium

    Cars drive towards a target at different speeds and can't overtake; count how many fleets arrive.

    Show answer

    Technique: Sort + stack of arrival times

    The clue: Cars can't pass, so a faster car behind joins the one ahead.

    The trick: Sort by position from closest to the target; compute arrival times; a car that would arrive sooner than the fleet ahead merges into it.

Hard

  1. Largest Rectangle In Histogram Hard

    Find the largest rectangle that fits inside a histogram.

    Show answer

    Technique: Monotonic increasing stack

    The clue: For each bar: how far can it stretch left and right before a shorter bar?

    The trick: Keep increasing heights on a stack; when a shorter bar arrives, pop and compute each popped bar's widest rectangle.

What to say in the interview

'Because we need to evaluate the most recently seen items first, I'll use a Stack to enforce Last-In-First-Out processing.'

Follow-up prep

How would you implement a Stack using only Queues?