📅  最后修改于: 2023-12-03 15:21:34.560000             🧑  作者: Mango
在计算机科学中,中位数是一个数据集的中间值。对于一个有序的整数序列(无论其中数据是有序的还是无序的),其中间位置的数值就是这个序列的中位数。
在实际问题中,有时候需要在数据流中动态地求取中位数,并且要求中位数只能为整数。这个问题可以通过构造两个堆来解决。
import heapq
class MedianFinder:
def __init__(self):
"""
initialize your data structure here.
"""
self.left_heap = []
self.right_heap = []
def addNum(self, num: int) -> None:
if len(self.left_heap) == len(self.right_heap):
heapq.heappush(self.left_heap, -heapq.heappushpop(self.right_heap, -num))
else:
heapq.heappush(self.right_heap, -heapq.heappushpop(self.left_heap, num))
def findMedian(self) -> float:
if len(self.left_heap) == len(self.right_heap):
return (self.left_heap[0] - self.right_heap[0]) / 2
else:
return float(self.left_heap[0])
class MedianFinder {
private Queue<Integer> leftHeap; // 小根堆
private Queue<Integer> rightHeap; // 大根堆
/** initialize your data structure here. */
public MedianFinder() {
leftHeap = new PriorityQueue<>();
rightHeap = new PriorityQueue<>((o1, o2) -> o2 - o1);
}
public void addNum(int num) {
if (leftHeap.size() == rightHeap.size()) {
rightHeap.offer(num);
leftHeap.offer(rightHeap.poll());
} else {
leftHeap.offer(num);
rightHeap.offer(leftHeap.poll());
}
}
public double findMedian() {
if (leftHeap.size() != rightHeap.size()) {
return leftHeap.peek();
} else {
return (leftHeap.peek() + rightHeap.peek()) / 2.0;
}
}
}
添加一个数的时间复杂度为 $O(\log{n})$,求中位数的时间复杂度为 $O(1)$。
空间复杂度为 $O(n)$,因为需要维护两个堆。
本算法适用于在数据流中动态地求取中位数的情况,尤其是在中位数必须为整数的情况下。