Maximum Frequency Stack

HardHash Map + Stacks · Design🧩 Data Structure DesignLeetCode #895 ↗Updated

Problem

Design a stack-like class FreqStack. push(val) adds an integer; pop() removes and returns the value that currently occurs most often in the stack. If several values tie on frequency, pop the one whose occurrence was pushed most recently.
Inputpush 5,7,5,7,4,5 then pop()Output5
Inputpop() pop() pop()Output7, 5, 4

0 ≤ val ≤ 109  ·  ≤ 2·104 calls  ·  pop only on a non-empty stack

Try it yourself

Java
class FreqStack {
    public void push(int val) {
        
    }

    public int pop() {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Think of the stack as layers by frequency: the k-th copy of a value goes onto stack k. Each layer is itself in push order, so the top of the highest layer is always the answer — and popping it never disturbs lower layers.
PatternData Structure Design

Instinct Implement a class whose methods must all hit a time bound (often O(1)) - write each method's target cost, then glue a hash map to a structure that keeps order.

Memory hack Finder plus keeper - a hash map finds it fast, a list/heap/array keeps the order, and every method updates both.

Open the Data Structure Design guide →

Approaches

Brute ForceOne Stack + Counts, Scan on Pop

Time O(1) push, O(n) popSpace O(n)

Keep a plain list in push order plus a frequency map. On pop, scan from the top down and keep the first value with a strictly larger count — scanning top-down makes ties resolve to the most recent one.

Java
class FreqStack {
    private final List<Integer> stack = new ArrayList<>();
    private final Map<Integer, Integer> freq = new HashMap<>();

    public void push(int val) {
        stack.add(val);
        freq.merge(val, 1, Integer::sum);
    }

    public int pop() {
        int best = -1;
        for (int i = stack.size() - 1; i >= 0; i--) {
            if (best == -1 || freq.get(stack.get(i)) > freq.get(stack.get(best))) best = i;
        }
        int val = stack.remove(best);   // O(n) shift
        freq.merge(val, -1, Integer::sum);
        return val;
    }
}

Straightforward, but every pop scans and shifts the whole stack.

At a glance

LevelApproachTimeSpace
Brute ForceOne Stack + Counts, Scan on PopO(1) push, O(n) popO(n)
BetterMax-Heap of (freq, time, val)O(log n) push/popO(n)
OptimalFrequency Map + Stack per FrequencyO(1) push/popO(n)
Common pitfalls
  • Moving a value between layers on push — keep old copies; just add to the new layer.
  • Scanning bottom-up in the brute force — ties then pop the oldest, not the newest.
  • Forgetting maxFreq-- when the top layer empties.
Interview tips
  • Restate the tie-break precisely: same frequency → most recently pushed.
  • Show the heap version first; then ask what order the heap really needs.
  • Draw the layers for 5,7,5,7,4,5 to prove the invariant.
Pattern
Bucket of stacks by count → O(1) “most frequent, then most recent” queries.
My notes saved in this browser