Skip to content

Commit 2c26ee9

Browse files
committed
feat: add solutions to lc problem: No.0895
No.0895.Maximum Frequency Stack
1 parent 822f86a commit 2c26ee9

File tree

9 files changed

+698
-21
lines changed

9 files changed

+698
-21
lines changed

solution/0600-0699/0628.Maximum Product of Three Numbers/README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,19 +84,19 @@ class Solution {
8484

8585
```go
8686
func maximumProduct(nums []int) int {
87-
n := len(nums)
88-
sort.Ints(nums)
87+
n := len(nums)
88+
sort.Ints(nums)
8989
// 全负 0 1 n-1
9090
// 全正 n-1 n-2 n-3
9191
// 有正有负 max([0 1 n-1], [n-1 n-2 n-3])
92-
return max(nums[0]*nums[1]*nums[n-1], nums[n-1]*nums[n-2]*nums[n-3])
92+
return max(nums[0]*nums[1]*nums[n-1], nums[n-1]*nums[n-2]*nums[n-3])
9393
}
9494

9595
func max(a, b int) int {
96-
if a > b {
97-
return a
98-
}
99-
return b
96+
if a > b {
97+
return a
98+
}
99+
return b
100100
}
101101
```
102102

solution/0600-0699/0628.Maximum Product of Three Numbers/README_EN.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,16 @@ class Solution {
5757

5858
```go
5959
func maximumProduct(nums []int) int {
60-
n := len(nums)
61-
sort.Ints(nums)
62-
return max(nums[0]*nums[1]*nums[n-1], nums[n-1]*nums[n-2]*nums[n-3])
60+
n := len(nums)
61+
sort.Ints(nums)
62+
return max(nums[0]*nums[1]*nums[n-1], nums[n-1]*nums[n-2]*nums[n-3])
6363
}
6464

6565
func max(a, b int) int {
66-
if a > b {
67-
return a
68-
}
69-
return b
66+
if a > b {
67+
return a
68+
}
69+
return b
7070
}
7171
```
7272

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
func maximumProduct(nums []int) int {
2-
n := len(nums)
3-
sort.Ints(nums)
4-
return max(nums[0]*nums[1]*nums[n-1], nums[n-1]*nums[n-2]*nums[n-3])
2+
n := len(nums)
3+
sort.Ints(nums)
4+
return max(nums[0]*nums[1]*nums[n-1], nums[n-1]*nums[n-2]*nums[n-3])
55
}
66

77
func max(a, b int) int {
8-
if a > b {
9-
return a
10-
}
11-
return b
8+
if a > b {
9+
return a
10+
}
11+
return b
1212
}

solution/0800-0899/0895.Maximum Frequency Stack/README.md

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,22 +56,307 @@ freqStack.pop ();//返回 4 ,因为 4, 5 和 7 出现频率最高,但 4 是
5656

5757
<!-- 这里可写通用的实现逻辑 -->
5858

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+
5979
<!-- tabs:start -->
6080

6181
### **Python3**
6282

6383
<!-- 这里可写当前语言的特殊实现逻辑 -->
6484

6585
```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
66102

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()
67135
```
68136

69137
### **Java**
70138

71139
<!-- 这里可写当前语言的特殊实现逻辑 -->
72140

73141
```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+
}
74353

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+
*/
75360
```
76361

77362
### **...**

0 commit comments

Comments
 (0)