◀ THE GRIND — STACK

Maximum Frequency Stack

The drill: Build a stack where pop always returns the most frequent value pushed so far — and among values tied for most frequent, the one pushed most recently wins.

THE BRIEFING — THE FULL DRILL, IN MY OWN WORDS

This drill builds a stack-like structure where pop doesn't simply return the most recently pushed value — it returns whichever value has been pushed the most times overall.

When two or more values are tied for the highest push count, pop favors whichever of them was pushed most recently. After a value is popped, its effective count for future comparisons drops by one.

Two operations get exercised: push, which adds a value, and pop, which removes and returns the value chosen by that frequency-then-recency rule.

EX 01
FreqStack()
push(8)
push(3)
push(8)
push(3)
push(6)
push(8)
pop() → 8
pop() → 3
pop() → 8
pop() → 6
pop() → 3
pop() → 8
FULL DRAIN THROUGH THREE TIES
EX 02
FreqStack()
push(9)
push(9)
push(9)
pop() → 9
pop() → 9
pop() → 9
ONE VALUE PUSHED THREE TIMES
EX 03
FreqStack()
push(1)
push(2)
pop() → 2
push(1)
pop() → 1
pop() → 1
RECENCY TIEBREAK, THEN FREQUENCY TAKES OVER
THE HINTS — TAKE ONLY WHAT YOU NEED
HINT 1 THE NUDGE

A plain stack only ever answers 'what came in last?'. This one also needs 'what's come in the most?' — what would you have to track alongside every push to answer that instantly?

HINT 2 THE STRUCTURE

Every value has its own mini push-history at each frequency level it has passed through. Group pushes by the frequency they just reached, not by the value itself.

HINT 3 ONE STEP FROM THE ANSWER

Keep freq[val], a map from frequency to a stack of values that reached it, and the running maxFreq. Pop from the max-frequency bucket, decrement that value's count, and drop maxFreq only when the bucket empties.

COACH'S BOARD — THE PATTERN, STEP BY STEP
FREQUENCY BUCKETSPATTERN · FREQUENCY BUCKETSpush(1) · push(2) · pop() · push(1) · pop() · pop()
push 1
push 2
pop
push 1
pop
pop
BUCKETS (freq → values) · maxFreq
— empty —
STEP 1

Bucket every push by the frequency it just reached. Pop always drains the top of the highest-frequency bucket.

STEP 1 / 8 · ← → WORK TOO
THE SPLITS — TWO PACES, TWO LANGUAGES
grind/maximum-frequency-stack.pyRACE PACE
LANG ▸
PACE ▸
class FreqStack:
    def __init__(self):
        self.freq = collections.Counter()
        self.group = collections.defaultdict(list)  # frequency -> values that reached it, push order
        self.maxFreq = 0

    def push(self, val: int) -> None:
        self.freq[val] += 1
        f = self.freq[val]
        self.maxFreq = max(self.maxFreq, f)
        self.group[f].append(val)

    def pop(self) -> int:
        val = self.group[self.maxFreq].pop()
        self.freq[val] -= 1
        if not self.group[self.maxFreq]:
            self.maxFreq -= 1
        return val
TIME O(1) ALL OPSSPACE O(N)PYTHON · RACE PACE · 18 LN

✓ CHIP-TIMED — ALL 4 SOLUTIONS RAN GREEN AGAINST SELF-AUTHORED CASES IN CI · JDK 21 · CPYTHON 3.12 · NOTHING PUBLISHES RED