LeetCode 题解工作台
求出 MK 平均值
给你两个整数 m 和 k ,以及数据流形式的若干整数。你需要实现一个数据结构,计算这个数据流的 MK 平均值 。 MK 平均值 按照如下步骤计算: 如果数据流中的整数少于 m 个, MK 平均值 为 -1 ,否则将数据流中最后 m 个元素拷贝到一个独立的容器中。 从这个容器中删除最小的 k 个数和最…
5
题型
4
代码语言
3
相关题
当前训练重点
困难 · 堆
答案摘要
我们可以维护以下数据结构或变量: - 一个长度为 的队列 ,其中队首元素为最早加入的元素,队尾元素为最近加入的元素;
Interview AiBoxInterview AiBox 实时 AI 助手,陪你讲清 堆 题型思路
题目描述
给你两个整数 m 和 k ,以及数据流形式的若干整数。你需要实现一个数据结构,计算这个数据流的 MK 平均值 。
MK 平均值 按照如下步骤计算:
- 如果数据流中的整数少于
m个,MK 平均值 为-1,否则将数据流中最后m个元素拷贝到一个独立的容器中。 - 从这个容器中删除最小的
k个数和最大的k个数。 - 计算剩余元素的平均值,并 向下取整到最近的整数 。
请你实现 MKAverage 类:
MKAverage(int m, int k)用一个空的数据流和两个整数m和k初始化 MKAverage 对象。void addElement(int num)往数据流中插入一个新的元素num。int calculateMKAverage()对当前的数据流计算并返回 MK 平均数 ,结果需 向下取整到最近的整数 。
示例 1:
输入:
["MKAverage", "addElement", "addElement", "calculateMKAverage", "addElement", "calculateMKAverage", "addElement", "addElement", "addElement", "calculateMKAverage"]
[[3, 1], [3], [1], [], [10], [], [5], [5], [5], []]
输出:
[null, null, null, -1, null, 3, null, null, null, 5]
解释:
MKAverage obj = new MKAverage(3, 1);
obj.addElement(3); // 当前元素为 [3]
obj.addElement(1); // 当前元素为 [3,1]
obj.calculateMKAverage(); // 返回 -1 ,因为 m = 3 ,但数据流中只有 2 个元素
obj.addElement(10); // 当前元素为 [3,1,10]
obj.calculateMKAverage(); // 最后 3 个元素为 [3,1,10]
// 删除最小以及最大的 1 个元素后,容器为 [3]
// [3] 的平均值等于 3/1 = 3 ,故返回 3
obj.addElement(5); // 当前元素为 [3,1,10,5]
obj.addElement(5); // 当前元素为 [3,1,10,5,5]
obj.addElement(5); // 当前元素为 [3,1,10,5,5,5]
obj.calculateMKAverage(); // 最后 3 个元素为 [5,5,5]
// 删除最小以及最大的 1 个元素后,容器为 [5]
// [5] 的平均值等于 5/1 = 5 ,故返回 5
提示:
3 <= m <= 1051 <= k*2 < m1 <= num <= 105addElement与calculateMKAverage总操作次数不超过105次。
解题思路
方法一:有序集合 + 队列
我们可以维护以下数据结构或变量:
- 一个长度为 的队列 ,其中队首元素为最早加入的元素,队尾元素为最近加入的元素;
- 三个有序集合,分别为 , , ,其中 和 分别存储最小的 个元素和最大的 个元素,而 存储剩余的元素;
- 一个变量 ,维护 中所有元素的和;
- 部分编程语言(如 Java, Go)额外维护两个变量 和 ,分别表示 和 中元素的个数。
调用 函数时,顺序执行以下操作:
- 如果 为空,或者 ,则将 加入 中;否则如果 为空,或者 ,则将 加入 中;否则将 加入 中,同时将 的值加到 中。
- 接下来将 加入队列 中,如果此时队列 的长度大于 ,则将队首元素 从队列 中移除,接下来从 , 或 中选择其中一个包含 的集合,将 从该集合中移除,如果该集合为 ,则将 减去 的值。
- 如果 的长度大于 ,则循环将 中的最大值 从 中移除,将 加入 中,同时将 加上 的值。
- 如果 的长度大于 ,则循环将 中的最小值 从 中移除,将 加入 中,同时将 加上 的值。
- 如果 的长度小于 ,并且 不为空,则循环将 中的最小值 从 中移除,将 加入 中,同时将 减去 的值。
- 如果 的长度小于 ,并且 不为空,则循环将 中的最大值 从 中移除,将 加入 中,同时将 减去 的值。
调用 函数时,如果 的长度小于 ,则返回 ,否则返回 。
时间复杂度方面,每次调用 函数的时间复杂度为 ,每次调用 函数的时间复杂度为 。空间复杂度为 。
class MKAverage:
def __init__(self, m: int, k: int):
self.m = m
self.k = k
self.s = 0
self.q = deque()
self.lo = SortedList()
self.mid = SortedList()
self.hi = SortedList()
def addElement(self, num: int) -> None:
if not self.lo or num <= self.lo[-1]:
self.lo.add(num)
elif not self.hi or num >= self.hi[0]:
self.hi.add(num)
else:
self.mid.add(num)
self.s += num
self.q.append(num)
if len(self.q) > self.m:
x = self.q.popleft()
if x in self.lo:
self.lo.remove(x)
elif x in self.hi:
self.hi.remove(x)
else:
self.mid.remove(x)
self.s -= x
while len(self.lo) > self.k:
x = self.lo.pop()
self.mid.add(x)
self.s += x
while len(self.hi) > self.k:
x = self.hi.pop(0)
self.mid.add(x)
self.s += x
while len(self.lo) < self.k and self.mid:
x = self.mid.pop(0)
self.lo.add(x)
self.s -= x
while len(self.hi) < self.k and self.mid:
x = self.mid.pop()
self.hi.add(x)
self.s -= x
def calculateMKAverage(self) -> int:
return -1 if len(self.q) < self.m else self.s // (self.m - 2 * self.k)
# Your MKAverage object will be instantiated and called as such:
# obj = MKAverage(m, k)
# obj.addElement(num)
# param_2 = obj.calculateMKAverage()
复杂度分析
| 指标 | 值 |
|---|---|
| 时间 | Depends on the final approach |
| 空间 | Depends on the final approach |
面试官常问的追问
外企场景- question_mark
Look for the candidate's understanding of sliding window techniques.
- question_mark
Gauge their ability to optimize the insertion and average calculation process.
- question_mark
Check if the candidate considers edge cases where `m` is small or the stream has fewer than `m` elements.
常见陷阱
外企场景- error
Not handling cases where the number of elements in the stream is less than `m` before the first `MKAverage` query.
- error
Inefficient recalculation of the average by re-sorting or scanning all `m` elements.
- error
Overcomplicating the solution by using unnecessary data structures, resulting in unnecessary time or space complexity.
进阶变体
外企场景- arrow_right_alt
Implement the solution using a deque to avoid sorting and ensure faster operations for average calculation.
- arrow_right_alt
Modify the problem to handle updates to the stream where elements can be removed or modified.
- arrow_right_alt
Extend the problem to calculate the MKAverage over different window sizes dynamically.