設計數據結構支持兩操作:
addNum(int num):從數據流添加整數findMedian():返回當前所有元素中位數中位數定義:有序列表中間值;偶數個元素取中間兩數平均值。例如 [2,3,4] → 3,[2,3] → 2.5。
maxHeap(大根堆):存較小一半元素,堆頂為最大值minHeap(小根堆):存較大一半元素,堆頂為最小值maxHeap.size() == minHeap.size() 或 maxHeap.size() == minHeap.size() + 1(maxHeap.top() + minHeap.top()) / 2.0maxHeap.top()(規定 maxHeap 多一個)minHeapminHeap 堆頂移至 maxHeapmaxHeap 尺寸超過 minHeap + 1,將 maxHeap 堆頂移回 minHeap這樣保證:所有 maxHeap 元素 ≤ 所有 minHeap 元素,且尺寸平衡。
// C++ Runtime: 212 ms
class MedianFinder {
priority_queue<int> maxHeap; // 大根堆(默認)
priority_queue<int, vector<int>, greater<int>> minHeap; // 小根堆
public:
void addNum(int num) {
minHeap.push(num);
maxHeap.push(minHeap.top()); minHeap.pop();
if (maxHeap.size() > minHeap.size() + 1) {
minHeap.push(maxHeap.top()); maxHeap.pop();
}
}
double findMedian() {
if (maxHeap.size() == minHeap.size())
return (maxHeap.top() + minHeap.top()) / 2.0;
else
return maxHeap.top();
}
};
// Java Runtime: 50 ms
class MedianFinder {
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
public void addNum(int num) {
minHeap.offer(num);
maxHeap.offer(minHeap.poll());
if (maxHeap.size() > minHeap.size())
minHeap.offer(maxHeap.poll());
}
public double findMedian() {
if (maxHeap.size() == minHeap.size())
return (maxHeap.peek() + minHeap.peek()) / 2.0;
else
return maxHeap.peek();
}
}
addNum:O(log n) 堆操作findMedian:O(1) 僅訪問堆頂multiset/TreeMap)或延遲刪除堆