Skip to content

Commit 56a8e91

Browse files
author
lucifer
committed
feat: 895 更新
1 parent 70cec6d commit 56a8e91

File tree

1 file changed

+46
-14
lines changed

1 file changed

+46
-14
lines changed

problems/895.maximum-frequency-stack.md

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pop() -> 返回 4 。
4848

4949
## 前置知识
5050

51+
- 设计题
5152
-
5253
- 哈希表
5354

@@ -57,31 +58,60 @@ pop() -> 返回 4 。
5758

5859
## 思路
5960

61+
设计题目基本都是选择好数据结构,那么算法实现就会很容易。 如果你不会这道题,并去看其他人的题解代码,会发现很多时候都比较容易理解。 你没有能做出来的原因很大程度上是因为**对基础数据结构**不熟悉。设计题基本不太会涉及到算法,如果有算法, 也比较有限,常见的有二分法。
62+
63+
对于这道题来说,我们需要涉及一个栈。 这个栈弹出的不是最近压入栈的,而是频率最高的。
64+
65+
> 实际上,这已经不是栈了,只是它愿意这么叫。
66+
67+
既然要弹出频率最高的,那么我们肯定要统计所有栈中数字的出现频率。由于数字范围比较大,因此使用哈希表是一个不错的选择。为了能更快的求出频率最高的,我们需要将频率最高的数字(或者其出现次数)存起来。
68+
69+
另外题目要求**如果最频繁的元素不只一个,则移除并返回最接近栈顶的元素**。我们不妨就使用一个栈 fraq_stack 来维护,将相同频率的数字放到一个栈中。这样频率相同的我们直接出栈就可以取到**最接近栈顶的元素**啦。存储结构为:
70+
71+
```
72+
{
73+
3: [1,2,3],
74+
2: [1,2,3,4],
75+
1: [1,2,3,4,5]
76+
}
77+
```
78+
79+
上面的结构表示 :
80+
81+
- 1,2,3 出现了 3 次
82+
- 4 出现了 2 次
83+
- 5 出现了 1 次
84+
85+
细心的同学可能发现了,频率为 2 的列表中同样存储了频率更高(这里是频率为 3)的数字。
86+
87+
这是故意的。比如我们将 3 弹出,那么 3 其实就变成了频率为 2 的数字了。这个时候,我们如何将 3 插入到频率为 2 的栈的正确位置呢?其实你只要按照我上面的数据结构进行设计就没有这个问题啦。
88+
6089
我们以题目给的例子来讲解。
6190

62-
- 使用fraq 来存储对应的数字出现次数。key 是数字,value频率
91+
- 使用 fraq 来存储对应的数字出现次数。key 是数字,value 频率
6392

6493
![](https://tva1.sinaimg.cn/large/007S8ZIlly1ghluav001bj30d00la74y.jpg)
6594

66-
- 由于题目限制“如果最频繁的元素不只一个,则移除并返回最接近栈顶的元素。”,我们考虑使用栈来维护一个频率表 fraq_stack。key是频率,value是数字组成的栈
95+
- 由于题目限制“如果最频繁的元素不只一个,则移除并返回最接近栈顶的元素。”,我们考虑使用栈来维护一个频率表 fraq_stack。key 是频率,value 是数字组成的栈
6796

6897
![](https://tva1.sinaimg.cn/large/007S8ZIlly1ghlub1bwg0j30k20i8gnh.jpg)
6998

70-
- 同时用max_fraq 记录当前的最大频率值。
99+
- 同时用 max_fraq 记录当前的最大频率值。
71100

72-
- 第一次pop的时候,我们最大的频率是3。由fraq_stack 知道我们需要pop掉5
101+
- 第一次 pop 的时候,我们最大的频率是 3。由 fraq_stack 知道我们需要 pop 掉 5
73102

74103
![](https://tva1.sinaimg.cn/large/007S8ZIlly1ghlub2e82vj31160nan00.jpg)
75104

76-
- 之后pop依次是这样的(红色数字表示顺序)
105+
- 之后 pop 依次是这样的(红色数字表示顺序)
77106

78107
![](https://tva1.sinaimg.cn/large/007S8ZIlly1ghlub3rxt5j30pk0kitb7.jpg)
79108

80109
## 关键点解析
81110

82111
- 栈的基本性质
83-
- hashtable的基本性质
84-
- push和pop的时候同时更新fraq,max_fraq 和 fraq_stack。
112+
- hashtable 的基本性质
113+
- fraq_stack 的设计。fraq_stack 中当前频率的栈要保存所有大于等于其频率的数字
114+
- push 和 pop 的时候同时更新 fraq,max_fraq 和 fraq_stack。
85115

86116
## 代码
87117

@@ -92,13 +122,13 @@ class FreqStack:
92122
self.fraq = collections.defaultdict(lambda: 0)
93123
self.fraq_stack = collections.defaultdict(list)
94124
self.max_fraq = 0
95-
125+
96126
def push(self, x: int) -> None:
97127
self.fraq[x] += 1
98128
if self.fraq[x] > self.max_fraq:
99129
self.max_fraq = self.fraq[x]
100-
self.fraq_stack[self.fraq[x]].append(x)
101-
130+
self.fraq_stack[self.fraq[x]].append(x)
131+
102132
def pop(self) -> int:
103133
ans = self.fraq_stack[self.max_fraq].pop()
104134
self.fraq[ans] -= 1
@@ -114,11 +144,13 @@ class FreqStack:
114144

115145
**复杂度分析**
116146

117-
- 时间复杂度:push 和 pop 平均时间复杂度是 $$O(1)$$
118-
- 空间复杂度:$$O(N)$$,其中N为数字的总数。
147+
这里的复杂度为均摊复杂度。
119148

120-
大家也可以关注我的公众号《脑洞前端》获取更多更新鲜的LeetCode题解
149+
- 时间复杂度:$O(1)$
150+
- 空间复杂度:$O(1)$
121151

122-
![](https://tva1.sinaimg.cn/large/007S8ZIlly1ghlub61ny5j31bi0hcq5s.jpg)
152+
更多题解可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 40K star 啦。
123153

154+
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。
124155

156+
![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfcuzagjalj30p00dwabs.jpg)

0 commit comments

Comments
 (0)