1. Brute Force

class FreqStack:

    def __init__(self):
        self.cnt = defaultdict(int)
        self.stack = []

    def push(self, val: int) -> None:
        self.stack.append(val)
        self.cnt[val] += 1

    def pop(self) -> int:
        maxCnt = max(self.cnt.values())
        i = len(self.stack) - 1
        while self.cnt[self.stack[i]] != maxCnt:
            i -= 1
        self.cnt[self.stack[i]] -= 1
        return self.stack.pop(i)

Time & Space Complexity

  • Time complexity:
    • O(1)O(1) time for each push()push() function call.
    • O(n)O(n) time for each pop()pop() function call.
  • Space complexity: O(n)O(n)

Where nn is the number of elements in the stack.


2. Heap

class FreqStack:

    def __init__(self):
        self.heap = []
        self.cnt = defaultdict(int)
        self.index = 0

    def push(self, val: int) -> None:
        self.cnt[val] += 1
        heapq.heappush(self.heap, (-self.cnt[val], -self.index, val))
        self.index += 1

    def pop(self) -> int:
        _, _, val = heapq.heappop(self.heap)
        self.cnt[val] -= 1
        return val

Time & Space Complexity

  • Time complexity:
    • O(logn)O(\log n) time for each push()push() function call.
    • O(logn)O(\log n) time for each pop()pop() function call.
  • Space complexity: O(n)O(n)

Where nn is the number of elements in the stack.


3. Stack Of Stacks (Hash Map)

class FreqStack:

    def __init__(self):
        self.cnt = {}
        self.maxCnt = 0
        self.stacks = {}

    def push(self, val: int) -> None:
        valCnt = 1 + self.cnt.get(val, 0)
        self.cnt[val] = valCnt
        if valCnt > self.maxCnt:
            self.maxCnt = valCnt
            self.stacks[valCnt] = []
        self.stacks[valCnt].append(val)

    def pop(self) -> int:
        res = self.stacks[self.maxCnt].pop()
        self.cnt[res] -= 1
        if not self.stacks[self.maxCnt]:
            self.maxCnt -= 1
        return res

Time & Space Complexity

  • Time complexity:
    • O(1)O(1) time for each push()push() function call.
    • O(1)O(1) time for each pop()pop() function call.
  • Space complexity: O(n)O(n)

Where nn is the number of elements in the stack.


4. Stack Of Stacks (Dynamic Array)

class FreqStack:

    def __init__(self):
        self.cnt = {}
        self.stacks = [[]]

    def push(self, val: int) -> None:
        valCnt = 1 + self.cnt.get(val, 0)
        self.cnt[val] = valCnt
        if valCnt == len(self.stacks):
            self.stacks.append([])
        self.stacks[valCnt].append(val)

    def pop(self) -> int:
        res = self.stacks[-1].pop()
        self.cnt[res] -= 1
        if not self.stacks[-1]:
            self.stacks.pop()
        return res

Time & Space Complexity

  • Time complexity:
    • O(1)O(1) time for each push()push() function call.
    • O(1)O(1) time for each pop()pop() function call.
  • Space complexity: O(n)O(n)

Where nn is the number of elements in the stack.