Skip to content

Commit 297d171

Browse files
authored
feat: add solutions to lc problem: No.2671 (doocs#2290)
No.2671.Frequency Tracker
1 parent 9d2d6bb commit 297d171

File tree

7 files changed

+106
-146
lines changed

7 files changed

+106
-146
lines changed

solution/2600-2699/2671.Frequency Tracker/README.md

Lines changed: 39 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,17 @@ frequencyTracker.hasFrequency(1); // 返回 true ,因为 3 出现 1 次
7979

8080
## 解法
8181

82-
### 方法一
82+
### 方法一:哈希表
83+
84+
我们定义两个哈希表,其中 $cnt$ 用于记录每个数字出现的次数,而 $freq$ 用于记录每个出现次数的数字的个数。
85+
86+
对于 `add` 操作,我们直接将哈希表 $freq$ 中 $cnt[number]$ 对应的值减一,然后将 $cnt[number]$ 加一,再将 $freq[cnt[number]]$ 对应的值加一。
87+
88+
对于 `deleteOne` 操作,我们首先判断 $cnt[number]$ 是否大于零,如果大于零,我们将哈希表 $freq$ 中 $cnt[number]$ 对应的值减一,然后将 $cnt[number]$ 减一,再将 $freq[cnt[number]]$ 对应的值加一。
89+
90+
对于 `hasFrequency` 操作,我们直接返回 $freq[frequency]$ 是否大于零。
91+
92+
时间复杂度方面,由于我们使用了哈希表,因此每个操作的时间复杂度均为 $O(1)$。空间复杂度 $O(n)$,其中 $n$ 为不同的数字的个数。
8393

8494
<!-- tabs:start -->
8595

@@ -90,17 +100,15 @@ class FrequencyTracker:
90100
self.freq = defaultdict(int)
91101

92102
def add(self, number: int) -> None:
93-
if self.freq[self.cnt[number]] > 0:
94-
self.freq[self.cnt[number]] -= 1
103+
self.freq[self.cnt[number]] -= 1
95104
self.cnt[number] += 1
96105
self.freq[self.cnt[number]] += 1
97106

98107
def deleteOne(self, number: int) -> None:
99-
if self.cnt[number] == 0:
100-
return
101-
self.freq[self.cnt[number]] -= 1
102-
self.cnt[number] -= 1
103-
self.freq[self.cnt[number]] += 1
108+
if self.cnt[number]:
109+
self.freq[self.cnt[number]] -= 1
110+
self.cnt[number] -= 1
111+
self.freq[self.cnt[number]] += 1
104112

105113
def hasFrequency(self, frequency: int) -> bool:
106114
return self.freq[frequency] > 0
@@ -122,22 +130,17 @@ class FrequencyTracker {
122130
}
123131

124132
public void add(int number) {
125-
int f = cnt.getOrDefault(number, 0);
126-
if (freq.getOrDefault(f, 0) > 0) {
127-
freq.merge(f, -1, Integer::sum);
128-
}
133+
freq.merge(cnt.getOrDefault(number, 0), -1, Integer::sum);
129134
cnt.merge(number, 1, Integer::sum);
130-
freq.merge(f + 1, 1, Integer::sum);
135+
freq.merge(cnt.get(number), 1, Integer::sum);
131136
}
132137

133138
public void deleteOne(int number) {
134-
int f = cnt.getOrDefault(number, 0);
135-
if (f == 0) {
136-
return;
139+
if (cnt.getOrDefault(number, 0) > 0) {
140+
freq.merge(cnt.get(number), -1, Integer::sum);
141+
cnt.merge(number, -1, Integer::sum);
142+
freq.merge(cnt.get(number), 1, Integer::sum);
137143
}
138-
freq.merge(f, -1, Integer::sum);
139-
cnt.merge(number, -1, Integer::sum);
140-
freq.merge(f - 1, 1, Integer::sum);
141144
}
142145

143146
public boolean hasFrequency(int frequency) {
@@ -161,22 +164,17 @@ public:
161164
}
162165

163166
void add(int number) {
164-
int f = cnt[number];
165-
if (f > 0) {
166-
freq[f]--;
167-
}
167+
freq[cnt[number]]--;
168168
cnt[number]++;
169-
freq[f + 1]++;
169+
freq[cnt[number]]++;
170170
}
171171

172172
void deleteOne(int number) {
173-
int f = cnt[number];
174-
if (f == 0) {
175-
return;
173+
if (cnt[number]) {
174+
freq[cnt[number]]--;
175+
cnt[number]--;
176+
freq[cnt[number]]++;
176177
}
177-
freq[f]--;
178-
cnt[number]--;
179-
freq[f - 1]++;
180178
}
181179

182180
bool hasFrequency(int frequency) {
@@ -208,22 +206,17 @@ func Constructor() FrequencyTracker {
208206
}
209207
210208
func (this *FrequencyTracker) Add(number int) {
211-
f := this.cnt[number]
212-
if f > 0 {
213-
this.freq[f]--
214-
}
209+
this.freq[this.cnt[number]]--
215210
this.cnt[number]++
216-
this.freq[f+1]++
211+
this.freq[this.cnt[number]]++
217212
}
218213
219214
func (this *FrequencyTracker) DeleteOne(number int) {
220-
f := this.cnt[number]
221-
if f == 0 {
222-
return
215+
if this.cnt[number] > 0 {
216+
this.freq[this.cnt[number]]--
217+
this.cnt[number]--
218+
this.freq[this.cnt[number]]++
223219
}
224-
this.freq[f]--
225-
this.cnt[number]--
226-
this.freq[f-1]++
227220
}
228221
229222
func (this *FrequencyTracker) HasFrequency(frequency int) bool {
@@ -251,21 +244,18 @@ class FrequencyTracker {
251244

252245
add(number: number): void {
253246
const f = this.cnt.get(number) || 0;
254-
if (f > 0) {
255-
this.freq.set(f, (this.freq.get(f) || 0) - 1);
256-
}
247+
this.freq.set(f, (this.freq.get(f) || 0) - 1);
257248
this.cnt.set(number, f + 1);
258249
this.freq.set(f + 1, (this.freq.get(f + 1) || 0) + 1);
259250
}
260251

261252
deleteOne(number: number): void {
262253
const f = this.cnt.get(number) || 0;
263-
if (f === 0) {
264-
return;
254+
if (f > 0) {
255+
this.freq.set(f, (this.freq.get(f) || 0) - 1);
256+
this.cnt.set(number, f - 1);
257+
this.freq.set(f - 1, (this.freq.get(f - 1) || 0) + 1);
265258
}
266-
this.freq.set(f, (this.freq.get(f) || 0) - 1);
267-
this.cnt.set(number, f - 1);
268-
this.freq.set(f - 1, (this.freq.get(f - 1) || 0) + 1);
269259
}
270260

271261
hasFrequency(frequency: number): boolean {

solution/2600-2699/2671.Frequency Tracker/README_EN.md

Lines changed: 39 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,17 @@ frequencyTracker.hasFrequency(1); // Returns true, because 3 occurs once
7878

7979
## Solutions
8080

81-
### Solution 1
81+
### Solution 1: Hash Table
82+
83+
We define two hash tables, where $cnt$ is used to record the occurrence count of each number, and $freq$ is used to record the count of numbers with each frequency.
84+
85+
For the `add` operation, we directly decrement the value corresponding to $cnt[number]$ in the hash table $freq$, then increment $cnt[number]$, and finally increment the value corresponding to $cnt[number]$ in $freq$.
86+
87+
For the `deleteOne` operation, we first check if $cnt[number]$ is greater than zero. If it is, we decrement the value corresponding to $cnt[number]$ in the hash table $freq$, then decrement $cnt[number]$, and finally increment the value corresponding to $cnt[number]$ in $freq$.
88+
89+
For the `hasFrequency` operation, we directly return whether $freq[frequency]$ is greater than zero.
90+
91+
In terms of time complexity, since we use hash tables, the time complexity of each operation is $O(1)$. The space complexity is $O(n)$, where $n$ is the number of distinct numbers.
8292

8393
<!-- tabs:start -->
8494

@@ -89,17 +99,15 @@ class FrequencyTracker:
8999
self.freq = defaultdict(int)
90100

91101
def add(self, number: int) -> None:
92-
if self.freq[self.cnt[number]] > 0:
93-
self.freq[self.cnt[number]] -= 1
102+
self.freq[self.cnt[number]] -= 1
94103
self.cnt[number] += 1
95104
self.freq[self.cnt[number]] += 1
96105

97106
def deleteOne(self, number: int) -> None:
98-
if self.cnt[number] == 0:
99-
return
100-
self.freq[self.cnt[number]] -= 1
101-
self.cnt[number] -= 1
102-
self.freq[self.cnt[number]] += 1
107+
if self.cnt[number]:
108+
self.freq[self.cnt[number]] -= 1
109+
self.cnt[number] -= 1
110+
self.freq[self.cnt[number]] += 1
103111

104112
def hasFrequency(self, frequency: int) -> bool:
105113
return self.freq[frequency] > 0
@@ -121,22 +129,17 @@ class FrequencyTracker {
121129
}
122130

123131
public void add(int number) {
124-
int f = cnt.getOrDefault(number, 0);
125-
if (freq.getOrDefault(f, 0) > 0) {
126-
freq.merge(f, -1, Integer::sum);
127-
}
132+
freq.merge(cnt.getOrDefault(number, 0), -1, Integer::sum);
128133
cnt.merge(number, 1, Integer::sum);
129-
freq.merge(f + 1, 1, Integer::sum);
134+
freq.merge(cnt.get(number), 1, Integer::sum);
130135
}
131136

132137
public void deleteOne(int number) {
133-
int f = cnt.getOrDefault(number, 0);
134-
if (f == 0) {
135-
return;
138+
if (cnt.getOrDefault(number, 0) > 0) {
139+
freq.merge(cnt.get(number), -1, Integer::sum);
140+
cnt.merge(number, -1, Integer::sum);
141+
freq.merge(cnt.get(number), 1, Integer::sum);
136142
}
137-
freq.merge(f, -1, Integer::sum);
138-
cnt.merge(number, -1, Integer::sum);
139-
freq.merge(f - 1, 1, Integer::sum);
140143
}
141144

142145
public boolean hasFrequency(int frequency) {
@@ -160,22 +163,17 @@ public:
160163
}
161164

162165
void add(int number) {
163-
int f = cnt[number];
164-
if (f > 0) {
165-
freq[f]--;
166-
}
166+
freq[cnt[number]]--;
167167
cnt[number]++;
168-
freq[f + 1]++;
168+
freq[cnt[number]]++;
169169
}
170170

171171
void deleteOne(int number) {
172-
int f = cnt[number];
173-
if (f == 0) {
174-
return;
172+
if (cnt[number]) {
173+
freq[cnt[number]]--;
174+
cnt[number]--;
175+
freq[cnt[number]]++;
175176
}
176-
freq[f]--;
177-
cnt[number]--;
178-
freq[f - 1]++;
179177
}
180178

181179
bool hasFrequency(int frequency) {
@@ -207,22 +205,17 @@ func Constructor() FrequencyTracker {
207205
}
208206
209207
func (this *FrequencyTracker) Add(number int) {
210-
f := this.cnt[number]
211-
if f > 0 {
212-
this.freq[f]--
213-
}
208+
this.freq[this.cnt[number]]--
214209
this.cnt[number]++
215-
this.freq[f+1]++
210+
this.freq[this.cnt[number]]++
216211
}
217212
218213
func (this *FrequencyTracker) DeleteOne(number int) {
219-
f := this.cnt[number]
220-
if f == 0 {
221-
return
214+
if this.cnt[number] > 0 {
215+
this.freq[this.cnt[number]]--
216+
this.cnt[number]--
217+
this.freq[this.cnt[number]]++
222218
}
223-
this.freq[f]--
224-
this.cnt[number]--
225-
this.freq[f-1]++
226219
}
227220
228221
func (this *FrequencyTracker) HasFrequency(frequency int) bool {
@@ -250,21 +243,18 @@ class FrequencyTracker {
250243

251244
add(number: number): void {
252245
const f = this.cnt.get(number) || 0;
253-
if (f > 0) {
254-
this.freq.set(f, (this.freq.get(f) || 0) - 1);
255-
}
246+
this.freq.set(f, (this.freq.get(f) || 0) - 1);
256247
this.cnt.set(number, f + 1);
257248
this.freq.set(f + 1, (this.freq.get(f + 1) || 0) + 1);
258249
}
259250

260251
deleteOne(number: number): void {
261252
const f = this.cnt.get(number) || 0;
262-
if (f === 0) {
263-
return;
253+
if (f > 0) {
254+
this.freq.set(f, (this.freq.get(f) || 0) - 1);
255+
this.cnt.set(number, f - 1);
256+
this.freq.set(f - 1, (this.freq.get(f - 1) || 0) + 1);
264257
}
265-
this.freq.set(f, (this.freq.get(f) || 0) - 1);
266-
this.cnt.set(number, f - 1);
267-
this.freq.set(f - 1, (this.freq.get(f - 1) || 0) + 1);
268258
}
269259

270260
hasFrequency(frequency: number): boolean {

solution/2600-2699/2671.Frequency Tracker/Solution.cpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,17 @@ class FrequencyTracker {
44
}
55

66
void add(int number) {
7-
int f = cnt[number];
8-
if (f > 0) {
9-
freq[f]--;
10-
}
7+
freq[cnt[number]]--;
118
cnt[number]++;
12-
freq[f + 1]++;
9+
freq[cnt[number]]++;
1310
}
1411

1512
void deleteOne(int number) {
16-
int f = cnt[number];
17-
if (f == 0) {
18-
return;
13+
if (cnt[number]) {
14+
freq[cnt[number]]--;
15+
cnt[number]--;
16+
freq[cnt[number]]++;
1917
}
20-
freq[f]--;
21-
cnt[number]--;
22-
freq[f - 1]++;
2318
}
2419

2520
bool hasFrequency(int frequency) {

solution/2600-2699/2671.Frequency Tracker/Solution.go

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,17 @@ func Constructor() FrequencyTracker {
88
}
99

1010
func (this *FrequencyTracker) Add(number int) {
11-
f := this.cnt[number]
12-
if f > 0 {
13-
this.freq[f]--
14-
}
11+
this.freq[this.cnt[number]]--
1512
this.cnt[number]++
16-
this.freq[f+1]++
13+
this.freq[this.cnt[number]]++
1714
}
1815

1916
func (this *FrequencyTracker) DeleteOne(number int) {
20-
f := this.cnt[number]
21-
if f == 0 {
22-
return
17+
if this.cnt[number] > 0 {
18+
this.freq[this.cnt[number]]--
19+
this.cnt[number]--
20+
this.freq[this.cnt[number]]++
2321
}
24-
this.freq[f]--
25-
this.cnt[number]--
26-
this.freq[f-1]++
2722
}
2823

2924
func (this *FrequencyTracker) HasFrequency(frequency int) bool {

solution/2600-2699/2671.Frequency Tracker/Solution.java

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,17 @@ public FrequencyTracker() {
66
}
77

88
public void add(int number) {
9-
int f = cnt.getOrDefault(number, 0);
10-
if (freq.getOrDefault(f, 0) > 0) {
11-
freq.merge(f, -1, Integer::sum);
12-
}
9+
freq.merge(cnt.getOrDefault(number, 0), -1, Integer::sum);
1310
cnt.merge(number, 1, Integer::sum);
14-
freq.merge(f + 1, 1, Integer::sum);
11+
freq.merge(cnt.get(number), 1, Integer::sum);
1512
}
1613

1714
public void deleteOne(int number) {
18-
int f = cnt.getOrDefault(number, 0);
19-
if (f == 0) {
20-
return;
15+
if (cnt.getOrDefault(number, 0) > 0) {
16+
freq.merge(cnt.get(number), -1, Integer::sum);
17+
cnt.merge(number, -1, Integer::sum);
18+
freq.merge(cnt.get(number), 1, Integer::sum);
2119
}
22-
freq.merge(f, -1, Integer::sum);
23-
cnt.merge(number, -1, Integer::sum);
24-
freq.merge(f - 1, 1, Integer::sum);
2520
}
2621

2722
public boolean hasFrequency(int frequency) {

0 commit comments

Comments
 (0)