Skip to main content

Maximum Frequency Stack


Maximum Frequency Stack: Design a stack-like data structure to push elements to the stack and pop the most frequent element from the stack.

Implement the FreqStack class:

  • FreqStack() constructs an empty frequency stack.
  • void push(int val) pushes an integer val onto the top of the stack.
  • int pop() removes and returns the most frequent element in the stack. If there is a tie for the most frequent element, the element closest to the stack's top is removed and returned.
Example 1:
Input
["FreqStack", "push", "push", "push", "push", "push", "push", "pop", "pop", "pop", "pop"]
[[], [5], [7], [5], [7], [4], [5], [], [], [], []]
Output
[null, null, null, null, null, null, null, 5, 7, 5, 4]

Explanation
FreqStack freqStack = new FreqStack();
freqStack.push(5); // The stack is [5]
freqStack.push(7); // The stack is [5,7]
freqStack.push(5); // The stack is [5,7,5]
freqStack.push(7); // The stack is [5,7,5,7]
freqStack.push(4); // The stack is [5,7,5,7,4]
freqStack.push(5); // The stack is [5,7,5,7,4,5]
freqStack.pop(); // return 5, as 5 is the most frequent.
The stack becomes [5,7,5,7,4].
freqStack.pop(); // return 7, as 5 and 7 is the most frequent,
but 7 is closest to the top. The stack becomes [5,7,5,4].
freqStack.pop(); // return 5, as 5 is the most frequent.
The stack becomes [5,7,4].
freqStack.pop(); // return 4, as 4, 5 and 7 is the most frequent,
but 4 is closest to the top. The stack becomes [5,7].

Constraints:
  • 0 <= val <= 10^9
  • At most 2 * 10^4 calls will be made to push and pop.
  • It is guaranteed that there will be at least one element in the stack before calling pop.

Try this Problem on your own or check similar problems:

  1. Top K Frequent Elements
Solution:
class FreqStack {
Map<Integer, Integer> freqMap;
List<Stack<Integer>> buckets;
public FreqStack() {
freqMap = new HashMap<>();
buckets = new ArrayList<>();
}

public void push(int val) {
int freq = freqMap.getOrDefault(val, 0) + 1;
if(freq > buckets.size()){
Stack<Integer> s = new Stack<>(){};
s.push(val);
buckets.add(s);
}else{
buckets.get(freq - 1).push(val);
}
freqMap.put(val, freq);
}

public int pop() {
int val = buckets.get(buckets.size() - 1).pop();
if(freqMap.get(val) - 1 == 0) freqMap.remove(val);
else freqMap.put(val, freqMap.get(val) - 1);
if(buckets.get(buckets.size() - 1).empty()) buckets.remove(buckets.size() - 1);
return val;
}
}

Time/Space Complexity:
  • Time Complexity: O(1)
  • Space Complexity: O(n)

Explanation:

It's a federation of data structures we use to solve this problem:

  • We keep a freqMap which keep track of occurrences of all numbers added to stack.
  • buckets list of stacks, one stack per frequency (like in bucket sort).

We have linear space complexity since we at most keep track of n elements added to the stack with constant time complexity. For the push we check the frequency of the val and if it can be placed in one of the frequency buckets. If it can't we create a new bucket with a new stack and push the val to it. We update the freqMap accordingly. For pop we get the last bucket and top of that bucket's stack and we return that value, while also checking if the bucket should be removed if it's empty and again update the freqMap counts.