leetcode的895最大频率栈题解,题目来自快手面经:https://www.nowcoder.com/discuss/493925109460135936

题目

895. 最大频率栈

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

实现 FreqStack 类:

  • FreqStack() 构造一个空的堆栈。
  • void push(int val) 将一个整数 val 压入栈顶。
  • int pop() 删除并返回堆栈中出现频率最高的元素。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
示例 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;
  • push 和 pop 的操作数不大于 2 * 104
  • 输入保证在调用 pop 之前堆栈中至少有一个元素。

思路

看到hard直接害怕,题解一看发现好像没有那么难……就是让我自己想恐怕是想不出来的。

用哈希表加栈就能解决这个问题,另外还需一个int变量维护当前最高频率是多少。

  • 一个哈希表用于元素和频率的计数
  • 一个哈希表用于频率和对应的栈

当插入元素的时候

  • 元素出现频率加一
  • 在对应频率的栈中插入元素(并不需要在之前的栈中删除元素)
  • 更新当前最高频率

当弹出元素的时候

  • 从最高频率的栈中弹出一个元素
  • 该元素出现频率减一
  • 如果最高频率的栈为空,则最高频率减一(因为每次都是以1的间隔增加的,所以减一的栈里面肯定会有元素)

这样就能很巧妙的实现题目需要的栈。

  • 哈希表中频率从低到高能理解为是一层栈,因为后入的频率高的数在栈顶;
  • 相同频率中又是一层栈;

即可以体现每一个数字的频率,又能保证栈的先入先出的特性!

代码

思路并不难,代码实现也很简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class FreqStack {
unordered_map<int,stack<int>> stMap; // 每个频率都有一个栈
unordered_map<int,int> countMap; // 频率计数
int maxFreq = 0; // 最高频率
public:
FreqStack() {}

void push(int val) {
// 将某个数字的频率加一
countMap[val]++;
stMap[countMap[val]].push(val);
maxFreq = max(maxFreq,countMap[val]);
}

int pop() {
// 从最高频率的栈中pop一个元素即可
int val = stMap[maxFreq].top();
stMap[maxFreq].pop();
// 频率减一
countMap[val]--;
// 如果最大频率栈没有内容,则减一
if(stMap[maxFreq].empty()){
maxFreq--;
}
return val;
}
};

/**
* Your FreqStack object will be instantiated and called as such:
* FreqStack* obj = new FreqStack();
* obj->push(val);
* int param_2 = obj->pop();
*/

image.png