leetcode
leetcode 801 ~ 850
最大频率栈

最大频率栈

难度:

标签:

题目描述

代码结果

运行时间: 184 ms, 内存: 24.8 MB


/*
思路:
1. 使用两个HashMap来记录元素的频率(freqMap)和频率对应的元素栈(freqStackMap)。
2. push操作:更新元素的频率,并将元素添加到对应频率的栈中。
3. pop操作:找到最高频率的栈,弹出栈顶元素并更新频率。
4. 使用Java Stream在操作集合时更简洁。
*/
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

public class FreqStack {
    private Map<Integer, Integer> freqMap;
    private Map<Integer, Stack<Integer>> freqStackMap;
    private int maxFreq;

    public FreqStack() {
        freqMap = new HashMap<>();
        freqStackMap = new HashMap<>();
        maxFreq = 0;
    }

    public void push(int val) {
        int freq = freqMap.getOrDefault(val, 0) + 1;
        freqMap.put(val, freq);
        if (freq > maxFreq) {
            maxFreq = freq;
        }
        freqStackMap.computeIfAbsent(freq, k -> new Stack<>()).push(val);
    }

    public int pop() {
        Stack<Integer> stack = freqStackMap.get(maxFreq);
        int val = stack.pop();
        if (stack.isEmpty()) {
            maxFreq--;
        }
        freqMap.put(val, freqMap.get(val) - 1);
        return val;
    }
}

解释

方法:

这个题解的思路是使用两个主要的数据结构:一个字典用来存储每个元素的出现频率,一个列表用来存储每个频率对应的元素集合。每次元素入栈时,更新该元素的频率,并将元素添加到对应频率的集合中。出栈时,从最高频率的集合中弹出元素,如果该集合为空,则移除该集合。

时间复杂度:

O(1)

空间复杂度:

O(n)

代码细节讲解

🦆
在实现FreqStack类的时候,你是如何确保pop操作始终返回最近入栈的出现频率最高的元素的?
在FreqStack实现中,元素栈`elems`是一个列表,其中每个索引位置存储一个列表,表示该频率下所有元素的集合。由于每次元素入栈时,都将其添加到其当前频率所对应的列表末尾,这保证了相同频率的元素按照入栈顺序存储。因此,当执行pop操作时,从`elems`中最后一个列表(即最高频率)的末尾弹出元素,这确保了返回的是最近入栈且出现频率最高的元素。
🦆
你提到使用字典来存储每个元素的出现频率,这种方法在所有情况下都能准确追踪频率变化吗,即使是在频繁的push和pop操作之后?
是的,使用字典`freq`来存储每个元素的出现频率是一个高效且准确的方法。字典提供常数时间复杂度的查找、插入和更新操作,这使得它非常适合频繁更新的场景。每次push操作都会增加元素的频率计数,而每次pop操作都会减少相应元素的频率计数。这种方法即便在频繁的push和pop操作后也能准确追踪每个元素的频率变化。
🦆
为什么选择使用列表来存储每个频率对应的元素集合而不是其他数据结构,比如堆或者平衡树?
选择使用列表来存储每个频率对应的元素集合主要是因为需要频繁地进行末尾元素的插入和移除操作,并且需要按顺序存储同一频率的元素以保持其入栈顺序。列表在这些操作中表现良好,尤其是在末尾添加或移除元素时具有常数时间复杂度。而使用堆或者平衡树虽然可以优化某些操作,但在维护元素的入栈顺序方面可能会更加复杂且效率较低。
🦆
在pop操作中,如果最高频率的集合为空,你会如何处理并确保操作的正确性?
在pop操作中,如果发现最高频率的集合为空,这意味着该频率下的所有元素都已被移除。在这种情况下,我会从`elems`列表中移除这个空的集合,确保列表`elems`的最后一个元素始终是非空的,代表当前的最高频率的元素集合。这样处理保证了每次pop操作都能正确地返回最高频率且最近入栈的元素,并且维护了数据结构的一致性和正确性。

相关问题