Skip to content

Commit 27aa11c

Browse files
committed
feat: add solutions to lc problem: No.1825
No.1825.Finding MK Average
1 parent ce7d600 commit 27aa11c

File tree

6 files changed

+1000
-0
lines changed

6 files changed

+1000
-0
lines changed

solution/1800-1899/1825.Finding MK Average/README.md

Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,22 +67,373 @@ obj.calculateMKAverage(); // 最后 3 个元素为 [5,5,5]
6767

6868
<!-- 这里可写通用的实现逻辑 -->
6969

70+
**方法一:有序集合 + 队列**
71+
72+
在本题中,我们需要维护的数据结构或变量有:
73+
74+
- 一个长度为 $m$ 的队列 $q$,其中队首元素为最早加入的元素,队尾元素为最近加入的元素
75+
- 三个有序集合,分别为 $lo$, $mid$, $hi$,其中 $lo$ 和 $hi$ 分别存储最小的 $k$ 个元素和最大的 $k$ 个元素,而 $mid$ 存储剩余的元素;
76+
- 一个变量 $s$,维护 $mid$ 中所有元素的和。
77+
- 部分编程语言(如 Java, Go)额外维护两个变量 $size1$ 和 $size3$,分别表示 $lo$ 和 $hi$ 中元素的个数。
78+
79+
调用 $addElement(num)$ 函数时,顺序执行以下操作:
80+
81+
1. 如果 $lo$ 为空,或者 $num \leq max(lo)$,则将 $num$ 加入 $lo$ 中;否则如果 $hi$ 为空,或者 $num \geq min(hi)$,则将 $num$ 加入 $hi$ 中;否则将 $num$ 加入 $mid$ 中,同时将 $num$ 的值加到 $s$ 中。
82+
1. 接下来将 $num$ 加入队列 $q$ 中,如果此时队列 $q$ 的长度大于 $m$,则将队首元素 $x$ 从队列 $q$ 中移除,接下来从 $lo$, $mid$ 或 $hi$ 中选择其中一个包含 $x$ 的集合,将 $x$ 从该集合中移除,如果该集合为 $mid$,则将 $s$ 减去 $x$ 的值。
83+
1. 如果 $lo$ 的长度大于 $k$,则循环将 $lo$ 中的最大值 $max(lo)$ 从 $lo$ 中移除,将 $max(lo)$ 加入 $mid$ 中,同时将 $s$ 加上 $max(lo)$ 的值。
84+
1. 如果 $hi$ 的长度大于 $k$,则循环将 $hi$ 中的最小值 $min(hi)$ 从 $hi$ 中移除,将 $min(hi)$ 加入 $mid$ 中,同时将 $s$ 加上 $min(hi)$ 的值。
85+
1. 如果 $lo$ 的长度小于 $k$,并且 $mid$ 不为空,则循环将 $mid$ 中的最小值 $min(mid)$ 从 $mid$ 中移除,将 $min(mid)$ 加入 $lo$ 中,同时将 $s$ 减去 $min(mid)$ 的值。
86+
1. 如果 $hi$ 的长度小于 $k$,并且 $mid$ 不为空,则循环将 $mid$ 中的最大值 $max(mid)$ 从 $mid$ 中移除,将 $max(mid)$ 加入 $hi$ 中,同时将 $s$ 减去 $max(mid)$ 的值。
87+
88+
调用 $calculateMKAverage()$ 函数时,如果 $q$ 的长度小于 $m$,则返回 $-1$,否则返回 $\frac{s}{m - 2k}$。
89+
90+
时间复杂度方面,每次调用 $addElement(num)$ 函数的时间复杂度为 $O(\log m)$,每次调用 $calculateMKAverage()$ 函数的时间复杂度为 $O(1)$。空间复杂度为 $O(m)$。
91+
7092
<!-- tabs:start -->
7193

7294
### **Python3**
7395

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

7698
```python
99+
from sortedcontainers import SortedList
100+
101+
102+
class MKAverage:
77103

104+
def __init__(self, m: int, k: int):
105+
self.m = m
106+
self.k = k
107+
self.s = 0
108+
self.q = deque()
109+
self.lo = SortedList()
110+
self.mid = SortedList()
111+
self.hi = SortedList()
112+
113+
def addElement(self, num: int) -> None:
114+
if not self.lo or num <= self.lo[-1]:
115+
self.lo.add(num)
116+
elif not self.hi or num >= self.hi[0]:
117+
self.hi.add(num)
118+
else:
119+
self.mid.add(num)
120+
self.s += num
121+
self.q.append(num)
122+
if len(self.q) > self.m:
123+
x = self.q.popleft()
124+
if x in self.lo:
125+
self.lo.remove(x)
126+
elif x in self.hi:
127+
self.hi.remove(x)
128+
else:
129+
self.mid.remove(x)
130+
self.s -= x
131+
while len(self.lo) > self.k:
132+
x = self.lo.pop()
133+
self.mid.add(x)
134+
self.s += x
135+
while len(self.hi) > self.k:
136+
x = self.hi.pop(0)
137+
self.mid.add(x)
138+
self.s += x
139+
while len(self.lo) < self.k and self.mid:
140+
x = self.mid.pop(0)
141+
self.lo.add(x)
142+
self.s -= x
143+
while len(self.hi) < self.k and self.mid:
144+
x = self.mid.pop()
145+
self.hi.add(x)
146+
self.s -= x
147+
148+
def calculateMKAverage(self) -> int:
149+
return -1 if len(self.q) < self.m else self.s // (self.m - 2 * self.k)
150+
151+
152+
# Your MKAverage object will be instantiated and called as such:
153+
# obj = MKAverage(m, k)
154+
# obj.addElement(num)
155+
# param_2 = obj.calculateMKAverage()
78156
```
79157

80158
### **Java**
81159

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

84162
```java
163+
class MKAverage {
164+
165+
private int m, k;
166+
private long s;
167+
private int size1, size3;
168+
private Deque<Integer> q = new ArrayDeque<>();
169+
private TreeMap<Integer, Integer> lo = new TreeMap<>();
170+
private TreeMap<Integer, Integer> mid = new TreeMap<>();
171+
private TreeMap<Integer, Integer> hi = new TreeMap<>();
172+
173+
174+
public MKAverage(int m, int k) {
175+
this.m = m;
176+
this.k = k;
177+
}
178+
179+
public void addElement(int num) {
180+
if (lo.isEmpty() || num <= lo.lastKey()) {
181+
lo.merge(num, 1, Integer::sum);
182+
++size1;
183+
} else if (hi.isEmpty() || num >= hi.firstKey()) {
184+
hi.merge(num, 1, Integer::sum);
185+
++size3;
186+
} else {
187+
mid.merge(num, 1, Integer::sum);
188+
s += num;
189+
}
190+
q.offer(num);
191+
if (q.size() > m) {
192+
int x = q.poll();
193+
if (lo.containsKey(x)) {
194+
lo.merge(x, -1, Integer::sum);
195+
if (lo.get(x) == 0) {
196+
lo.remove(x);
197+
}
198+
--size1;
199+
} else if (hi.containsKey(x)) {
200+
hi.merge(x, -1, Integer::sum);
201+
if (hi.get(x) == 0) {
202+
hi.remove(x);
203+
}
204+
--size3;
205+
} else {
206+
mid.merge(x, -1, Integer::sum);
207+
if (mid.get(x) == 0) {
208+
mid.remove(x);
209+
}
210+
s -= x;
211+
}
212+
}
213+
for (; size1 > k; --size1) {
214+
int x = lo.lastKey();
215+
lo.merge(x, -1, Integer::sum);
216+
if (lo.get(x) == 0) {
217+
lo.remove(x);
218+
}
219+
mid.merge(x, 1, Integer::sum);
220+
s += x;
221+
}
222+
for (; size3 > k; --size3) {
223+
int x = hi.firstKey();
224+
hi.merge(x, -1, Integer::sum);
225+
if (hi.get(x) == 0) {
226+
hi.remove(x);
227+
}
228+
mid.merge(x, 1, Integer::sum);
229+
s += x;
230+
}
231+
for (; size1 < k && !mid.isEmpty(); ++size1) {
232+
int x = mid.firstKey();
233+
mid.merge(x, -1, Integer::sum);
234+
if (mid.get(x) == 0) {
235+
mid.remove(x);
236+
}
237+
s -= x;
238+
lo.merge(x, 1, Integer::sum);
239+
}
240+
for (; size3 < k && !mid.isEmpty(); ++size3) {
241+
int x = mid.lastKey();
242+
mid.merge(x, -1, Integer::sum);
243+
if (mid.get(x) == 0) {
244+
mid.remove(x);
245+
}
246+
s -= x;
247+
hi.merge(x, 1, Integer::sum);
248+
}
249+
}
250+
251+
public int calculateMKAverage() {
252+
return q.size() < m ? -1 : (int) (s / (q.size() - k * 2));
253+
}
254+
}
255+
256+
/**
257+
* Your MKAverage object will be instantiated and called as such:
258+
* MKAverage obj = new MKAverage(m, k);
259+
* obj.addElement(num);
260+
* int param_2 = obj.calculateMKAverage();
261+
*/
262+
```
263+
264+
### **C++**
265+
266+
```cpp
267+
class MKAverage {
268+
public:
269+
MKAverage(int m, int k) {
270+
this->m = m;
271+
this->k = k;
272+
}
273+
274+
void addElement(int num) {
275+
if (lo.empty() || num <= *lo.rbegin()) {
276+
lo.insert(num);
277+
} else if (hi.empty() || num >= *hi.begin()) {
278+
hi.insert(num);
279+
} else {
280+
mid.insert(num);
281+
s += num;
282+
}
283+
284+
q.push(num);
285+
if (q.size() > m) {
286+
int x = q.front();
287+
q.pop();
288+
if (lo.find(x) != lo.end()) {
289+
lo.erase(lo.find(x));
290+
} else if (hi.find(x) != hi.end()) {
291+
hi.erase(hi.find(x));
292+
} else {
293+
mid.erase(mid.find(x));
294+
s -= x;
295+
}
296+
}
297+
while (lo.size() > k) {
298+
int x = *lo.rbegin();
299+
lo.erase(prev(lo.end()));
300+
mid.insert(x);
301+
s += x;
302+
}
303+
while (hi.size() > k) {
304+
int x = *hi.begin();
305+
hi.erase(hi.begin());
306+
mid.insert(x);
307+
s += x;
308+
}
309+
while (lo.size() < k && mid.size()) {
310+
int x = *mid.begin();
311+
mid.erase(mid.begin());
312+
s -= x;
313+
lo.insert(x);
314+
}
315+
while (hi.size() < k && mid.size()) {
316+
int x = *mid.rbegin();
317+
mid.erase(prev(mid.end()));
318+
s -= x;
319+
hi.insert(x);
320+
}
321+
}
322+
323+
int calculateMKAverage() {
324+
return q.size() < m ? -1 : s / (q.size() - k * 2);
325+
}
326+
327+
private:
328+
int m, k;
329+
long long s = 0;
330+
queue<int> q;
331+
multiset<int> lo, mid, hi;
332+
};
333+
334+
/**
335+
* Your MKAverage object will be instantiated and called as such:
336+
* MKAverage* obj = new MKAverage(m, k);
337+
* obj->addElement(num);
338+
* int param_2 = obj->calculateMKAverage();
339+
*/
340+
```
341+
342+
### **Go**
343+
344+
```go
345+
type MKAverage struct {
346+
lo, mid, hi *redblacktree.Tree
347+
q []int
348+
m, k, s int
349+
size1, size3 int
350+
}
351+
352+
func Constructor(m int, k int) MKAverage {
353+
lo := redblacktree.NewWithIntComparator()
354+
mid := redblacktree.NewWithIntComparator()
355+
hi := redblacktree.NewWithIntComparator()
356+
return MKAverage{lo, mid, hi, []int{}, m, k, 0, 0, 0}
357+
}
358+
359+
func (this *MKAverage) AddElement(num int) {
360+
merge := func(rbt *redblacktree.Tree, key, value int) {
361+
if v, ok := rbt.Get(key); ok {
362+
nxt := v.(int) + value
363+
if nxt == 0 {
364+
rbt.Remove(key)
365+
} else {
366+
rbt.Put(key, nxt)
367+
}
368+
} else {
369+
rbt.Put(key, value)
370+
}
371+
}
372+
373+
if this.lo.Empty() || num <= this.lo.Right().Key.(int) {
374+
merge(this.lo, num, 1)
375+
this.size1++
376+
} else if this.hi.Empty() || num >= this.hi.Left().Key.(int) {
377+
merge(this.hi, num, 1)
378+
this.size3++
379+
} else {
380+
merge(this.mid, num, 1)
381+
this.s += num
382+
}
383+
this.q = append(this.q, num)
384+
if len(this.q) > this.m {
385+
x := this.q[0]
386+
this.q = this.q[1:]
387+
if _, ok := this.lo.Get(x); ok {
388+
merge(this.lo, x, -1)
389+
this.size1--
390+
} else if _, ok := this.hi.Get(x); ok {
391+
merge(this.hi, x, -1)
392+
this.size3--
393+
} else {
394+
merge(this.mid, x, -1)
395+
this.s -= x
396+
}
397+
}
398+
for ; this.size1 > this.k; this.size1-- {
399+
x := this.lo.Right().Key.(int)
400+
merge(this.lo, x, -1)
401+
merge(this.mid, x, 1)
402+
this.s += x
403+
}
404+
for ; this.size3 > this.k; this.size3-- {
405+
x := this.hi.Left().Key.(int)
406+
merge(this.hi, x, -1)
407+
merge(this.mid, x, 1)
408+
this.s += x
409+
}
410+
for ; this.size1 < this.k && !this.mid.Empty(); this.size1++ {
411+
x := this.mid.Left().Key.(int)
412+
merge(this.mid, x, -1)
413+
this.s -= x
414+
merge(this.lo, x, 1)
415+
}
416+
for ; this.size3 < this.k && !this.mid.Empty(); this.size3++ {
417+
x := this.mid.Right().Key.(int)
418+
merge(this.mid, x, -1)
419+
this.s -= x
420+
merge(this.hi, x, 1)
421+
}
422+
}
423+
424+
func (this *MKAverage) CalculateMKAverage() int {
425+
if len(this.q) < this.m {
426+
return -1
427+
}
428+
return this.s / (this.m - 2*this.k)
429+
}
85430

431+
/**
432+
* Your MKAverage object will be instantiated and called as such:
433+
* obj := Constructor(m, k);
434+
* obj.AddElement(num);
435+
* param_2 := obj.CalculateMKAverage();
436+
*/
86437
```
87438

88439
### **...**

0 commit comments

Comments
 (0)