895. 最大频率栈(难度:困难)
2024-04-09 22:20:55  阅读数 343

题目链接:https://leetcode.cn/problems/maximum-frequency-stack/

题目描述:

设计一个类似堆栈的数据结构,将元素推入堆栈,并从堆栈中弹出出现频率最高的元素。

实现 FreqStack 类:

  • FreqStack() 构造一个空的堆栈。

  • void push(int val) 将一个整数 val 压入栈顶。

  • int pop()
    

    删除并返回堆栈中出现频率最高的元素。

    • 如果出现频率最高的元素不只一个,则移除并返回最接近栈顶的元素。

示例 1:

输入:
["FreqStack","push","push","push","push","push","push","pop","pop","pop","pop"],
[[],[5],[7],[5],[7],[4],[5],[],[],[],[]]
输出:[null,null,null,null,null,null,null,5,7,5,4]
解释:
FreqStack = new FreqStack();
freqStack.push (5);//堆栈为 [5]
freqStack.push (7);//堆栈是 [5,7]
freqStack.push (5);//堆栈是 [5,7,5]
freqStack.push (7);//堆栈是 [5,7,5,7]
freqStack.push (4);//堆栈是 [5,7,5,7,4]
freqStack.push (5);//堆栈是 [5,7,5,7,4,5]
freqStack.pop ();//返回 5 ,因为 5 出现频率最高。堆栈变成 [5,7,5,7,4]。
freqStack.pop ();//返回 7 ,因为 5 和 7 出现频率最高,但7最接近顶部。堆栈变成 [5,7,5,4]。
freqStack.pop ();//返回 5 ,因为 5 出现频率最高。堆栈变成 [5,7,4]。
freqStack.pop ();//返回 4 ,因为 4, 5 和 7 出现频率最高,但 4 是最接近顶部的。堆栈变成 [5,7]。

提示:

  • 0 <= val <= 109
  • pushpop 的操作数不大于 2 * 104
  • 输入保证在调用 pop 之前堆栈中至少有一个元素。

解法:

使用一个Map<Integer, Integer> map存放数字val对应出现的次数,使用LinkedList<Integer>[] st 存储出现N次,对应的数字集合,使用 int max 来记录当前出现的最大次数。

push一个 val 时,先更新val的出现次数times =map.getOrDefault(val, 0) + 1,再在对应次数的st[times].add(val),更新当前最大出现次数max = Math.max(max, times)

pop 最大出现次数且最后一个入栈的元素时,只需要取出result = st[max].removeLast() 就是需要出栈的元素,再将该元素出现次数 -1即可。

class FreqStack {
    //存放数字val对应出现的次数
    Map<Integer, Integer> map = new HashMap<>();
    //存储出现N次,对应的数字集合
    LinkedList<Integer>[] st = new LinkedList[2 * (int) 1e4];
    //当前最大的出现次数
    int max = 0;

    public FreqStack() {
    }

    public void push(int val) {
        // 将val出现的次数+1
        int time = map.getOrDefault(val, 0) + 1;
        map.put(val, time);
        if (st[time] == null) {
            st[time] = new LinkedList<>();
        }
        st[time].add(val);
        max = Math.max(max, time);
    }

    public int pop() {
        int result = -1;
        while (max > 0) {
            if (st[max].size() == 0) {
                max--;
            } else {
                //将最后一个元素,即最后一个入队列的元素出栈。
                result = st[max].removeLast();
                break;
            }
        }
        // 将该元素出现次数-1
        map.put(result, map.getOrDefault(result, 0) - 1);
        return result;
    }
}