@@ -56,22 +56,307 @@ freqStack.pop ();//返回 4 ,因为 4, 5 和 7 出现频率最高,但 4 是
56
56
57
57
<!-- 这里可写通用的实现逻辑 -->
58
58
59
+ ** 方法一:哈希表 + 优先队列(大根堆)**
60
+
61
+ 根据题目描述,我们需要设计一个支持弹出“出现频率最高”的元素的数据结构。如果存在多个元素出现频率相同,那么弹出最接近栈顶的元素。
62
+
63
+ 我们可以使用哈希表 $cnt$ 记录每个元素出现的频率,用一个优先队列(大根堆) $q$ 维护元素频率以及对应的压栈时间戳。
64
+
65
+ 执行压栈操作时,我们先将当前时间戳加一,即 $ts \gets ts + 1$;然后将元素 $x$ 的频率加一,即 $cnt[ val] \gets cnt[ val] + 1$,最后将三元组 $(cnt[ val] , ts, val)$ 加入优先队列 $q$ 中。压栈操作的时间复杂度为 $O(\log n)$。
66
+
67
+ 执行弹栈操作时,我们直接从优先队列 $q$ 中弹出一个元素即可。由于优先队列 $q$ 中的元素按照频率降序排序,因此弹出的元素一定是出现频率最高的元素。如果存在多个元素出现频率相同,那么弹出最接近栈顶的元素,即弹出时间戳最大的元素。弹出后,我们将弹出元素的频率减一,即 $cnt[ val] \gets cnt[ val] - 1$。弹栈操作的时间复杂度为 $O(\log n)$。
68
+
69
+ ** 方法二:双哈希表**
70
+
71
+ 在方法一中,为了能弹出符合要求的元素,我们维护了一个优先队列,每次都需要对优先队列进行操作,时间复杂度为 $O(\log n)$。如果我们能够在 $O(1)$ 的时间内找到符合要求的元素,那么整个数据结构每次操作的时间复杂度就可以降低到 $O(1)$。
72
+
73
+ 实际上,我们可以用一个变量 $mx$ 记录当前出现频率的最大值,用一个哈希表 $d$ 记录每个出现频率对应的元素列表,与方法一相同,用一个哈希表 $cnt$ 记录每个元素出现的频率。
74
+
75
+ 执行压栈操作时,我们将元素的频率加一,即 $cnt[ val] \gets cnt[ val] + 1$,然后将元素 $val$ 加入哈希表 $d$ 中对应的频率列表中,即 $d[ cnt[ val]] .push(val)$。如果当前元素的频率大于 $mx$,则更新 $mx$,即 $mx \gets cnt[ val] $。压栈操作的时间复杂度为 $O(1)$。
76
+
77
+ 执行弹栈操作时,我们从哈希表 $d$ 中取出频率为 $mx$ 的元素列表,弹出列表中的最后一个元素 $val$,然后将 $val$ 从哈希表 $d$ 中移除,即 $d[ mx] .pop()$。最后将 $val$ 的频率减一,即 $cnt[ val] \gets cnt[ val] - 1$。如果 $d[ mx] $ 列表为空,说明当前出现频率最大的元素已经全部弹出,我们需要将 $mx$ 减一,即 $mx \gets mx - 1$。弹栈操作的时间复杂度为 $O(1)$。
78
+
59
79
<!-- tabs:start -->
60
80
61
81
### ** Python3**
62
82
63
83
<!-- 这里可写当前语言的特殊实现逻辑 -->
64
84
65
85
``` python
86
+ class FreqStack :
87
+
88
+ def __init__ (self ):
89
+ self .cnt = defaultdict(int )
90
+ self .q = []
91
+ self .ts = 0
92
+
93
+ def push (self , val : int ) -> None :
94
+ self .ts += 1
95
+ self .cnt[val] += 1
96
+ heappush(self .q, (- self .cnt[val], - self .ts, val))
97
+
98
+ def pop (self ) -> int :
99
+ val = heappop(self .q)[2 ]
100
+ self .cnt[val] -= 1
101
+ return val
66
102
103
+
104
+ # Your FreqStack object will be instantiated and called as such:
105
+ # obj = FreqStack()
106
+ # obj.push(val)
107
+ # param_2 = obj.pop()
108
+ ```
109
+
110
+ ``` python
111
+ class FreqStack :
112
+
113
+ def __init__ (self ):
114
+ self .cnt = defaultdict(int )
115
+ self .d = defaultdict(list )
116
+ self .mx = 0
117
+
118
+ def push (self , val : int ) -> None :
119
+ self .cnt[val] += 1
120
+ self .d[self .cnt[val]].append(val)
121
+ self .mx = max (self .mx, self .cnt[val])
122
+
123
+ def pop (self ) -> int :
124
+ val = self .d[self .mx].pop()
125
+ self .cnt[val] -= 1
126
+ if not self .d[self .mx]:
127
+ self .mx -= 1
128
+ return val
129
+
130
+
131
+ # Your FreqStack object will be instantiated and called as such:
132
+ # obj = FreqStack()
133
+ # obj.push(val)
134
+ # param_2 = obj.pop()
67
135
```
68
136
69
137
### ** Java**
70
138
71
139
<!-- 这里可写当前语言的特殊实现逻辑 -->
72
140
73
141
``` java
142
+ class FreqStack {
143
+ private Map<Integer , Integer > cnt = new HashMap<> ();
144
+ private PriorityQueue<int[]> q = new PriorityQueue<> ((a, b) - > a[0 ] == b[0 ] ? b[1 ] - a[1 ] : b[0 ] - a[0 ]);
145
+ private int ts;
146
+
147
+ public FreqStack () {
148
+
149
+ }
150
+
151
+ public void push (int val ) {
152
+ cnt. put(val, cnt. getOrDefault(val, 0 ) + 1 );
153
+ q. offer(new int [] {cnt. get(val), ++ ts, val});
154
+ }
155
+
156
+ public int pop () {
157
+ int val = q. poll()[2 ];
158
+ cnt. put(val, cnt. get(val) - 1 );
159
+ return val;
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Your FreqStack object will be instantiated and called as such:
165
+ * FreqStack obj = new FreqStack();
166
+ * obj.push(val);
167
+ * int param_2 = obj.pop();
168
+ */
169
+ ```
170
+
171
+ ``` java
172
+ class FreqStack {
173
+ private Map<Integer , Integer > cnt = new HashMap<> ();
174
+ private Map<Integer , Deque<Integer > > d = new HashMap<> ();
175
+ private int mx;
176
+
177
+ public FreqStack () {
178
+
179
+ }
180
+
181
+ public void push (int val ) {
182
+ cnt. put(val, cnt. getOrDefault(val, 0 ) + 1 );
183
+ int t = cnt. get(val);
184
+ d. computeIfAbsent(t, k - > new ArrayDeque<> ()). push(val);
185
+ mx = Math . max(mx, t);
186
+ }
187
+
188
+ public int pop () {
189
+ int val = d. get(mx). pop();
190
+ cnt. put(val, cnt. get(val) - 1 );
191
+ if (d. get(mx). isEmpty()) {
192
+ -- mx;
193
+ }
194
+ return val;
195
+ }
196
+ }
197
+
198
+ /**
199
+ * Your FreqStack object will be instantiated and called as such:
200
+ * FreqStack obj = new FreqStack();
201
+ * obj.push(val);
202
+ * int param_2 = obj.pop();
203
+ */
204
+ ```
205
+
206
+ ### ** C++**
207
+
208
+ ``` cpp
209
+ class FreqStack {
210
+ public:
211
+ FreqStack() {
212
+
213
+ }
214
+
215
+ void push (int val) {
216
+ ++cnt[ val] ;
217
+ q.emplace(cnt[ val] , ++ts, val);
218
+ }
219
+
220
+ int pop() {
221
+ auto [a, b, val] = q.top();
222
+ q.pop();
223
+ --cnt[val];
224
+ return val;
225
+ }
226
+
227
+ private:
228
+ unordered_map<int, int> cnt;
229
+ priority_queue<tuple<int, int, int>> q;
230
+ int ts = 0;
231
+ };
232
+
233
+ /**
234
+ * Your FreqStack object will be instantiated and called as such:
235
+ * FreqStack* obj = new FreqStack();
236
+ * obj->push(val);
237
+ * int param_2 = obj->pop();
238
+ * /
239
+ ```
240
+
241
+ ```cpp
242
+ class FreqStack {
243
+ public:
244
+ FreqStack() {
245
+
246
+ }
247
+
248
+ void push(int val) {
249
+ ++cnt[val];
250
+ d[cnt[val]].push(val);
251
+ mx = max(mx, cnt[val]);
252
+ }
253
+
254
+ int pop() {
255
+ int val = d[mx].top();
256
+ --cnt[val];
257
+ d[mx].pop();
258
+ if (d[mx].empty()) --mx;
259
+ return val;
260
+ }
261
+
262
+ private:
263
+ unordered_map<int, int> cnt;
264
+ unordered_map<int, stack<int>> d;
265
+ int mx = 0;
266
+ };
267
+
268
+ /**
269
+ * Your FreqStack object will be instantiated and called as such:
270
+ * FreqStack* obj = new FreqStack();
271
+ * obj->push(val);
272
+ * int param_2 = obj->pop();
273
+ */
274
+ ```
275
+
276
+ ### ** Go**
277
+
278
+ ``` go
279
+ type FreqStack struct {
280
+ cnt map [int ]int
281
+ q hp
282
+ ts int
283
+ }
284
+
285
+ func Constructor () FreqStack {
286
+ return FreqStack{map [int ]int {}, hp{}, 0 }
287
+ }
288
+
289
+ func (this *FreqStack ) Push (val int ) {
290
+ this.cnt [val]++
291
+ this.ts ++
292
+ heap.Push (&this.q , tuple{this.cnt [val], this.ts , val})
293
+ }
294
+
295
+ func (this *FreqStack ) Pop () int {
296
+ val := heap.Pop (&this.q ).(tuple).val
297
+ this.cnt [val]--
298
+ return val
299
+ }
300
+
301
+ type tuple struct { cnt, ts, val int }
302
+ type hp []tuple
303
+
304
+ func (h hp ) Len () int { return len (h) }
305
+ func (h hp ) Less (i , j int ) bool {
306
+ return h[i].cnt > h[j].cnt || h[i].cnt == h[j].cnt && h[i].ts > h[j].ts
307
+ }
308
+ func (h hp ) Swap (i , j int ) { h[i], h[j] = h[j], h[i] }
309
+ func (h *hp ) Push (v interface {}) { *h = append (*h, v.(tuple)) }
310
+ func (h *hp ) Pop () interface {} { a := *h; v := a[len (a)-1 ]; *h = a[:len (a)-1 ]; return v }
311
+
312
+ /* *
313
+ * Your FreqStack object will be instantiated and called as such:
314
+ * obj := Constructor();
315
+ * obj.Push(val);
316
+ * param_2 := obj.Pop();
317
+ */
318
+ ```
319
+
320
+ ``` go
321
+ type FreqStack struct {
322
+ cnt map [int ]int
323
+ d map [int ][]int
324
+ mx int
325
+ }
326
+
327
+ func Constructor () FreqStack {
328
+ return FreqStack{map [int ]int {}, map [int ][]int {}, 0 }
329
+ }
330
+
331
+ func (this *FreqStack ) Push (val int ) {
332
+ this.cnt [val]++
333
+ this.d [this.cnt [val]] = append (this.d [this.cnt [val]], val)
334
+ this.mx = max (this.mx , this.cnt [val])
335
+ }
336
+
337
+ func (this *FreqStack ) Pop () int {
338
+ val := this.d [this.mx ][len (this.d [this.mx ])-1 ]
339
+ this.d [this.mx ] = this.d [this.mx ][:len (this.d [this.mx ])-1 ]
340
+ this.cnt [val]--
341
+ if len (this.d [this.mx ]) == 0 {
342
+ this.mx --
343
+ }
344
+ return val
345
+ }
346
+
347
+ func max (a , b int ) int {
348
+ if a > b {
349
+ return a
350
+ }
351
+ return b
352
+ }
74
353
354
+ /* *
355
+ * Your FreqStack object will be instantiated and called as such:
356
+ * obj := Constructor();
357
+ * obj.Push(val);
358
+ * param_2 := obj.Pop();
359
+ */
75
360
```
76
361
77
362
### ** ...**
0 commit comments