本文共 1534 字,大约阅读时间需要 5 分钟。
中位数是有序列表中间的数。如果列表长度为偶数,中位数是中间两个数的平均值。例如:
我们需要设计一个支持以下两种操作的数据结构:
本题中,我们选择使用堆(优先队列)这种数据结构。
将数据分为两部分:
为了保证动态操作过程中两个堆的数据量差不超过 1,我们在添加新元素时,会先将其添加到最大堆。在此基础上,如果最大堆的大小小于最小堆的大小,则将最大堆的最大元素移动到最小堆中。
import java.util.PriorityQueue;class MedianFinder { PriorityQueue minHeap; PriorityQueue(Integer> maxHeap; public MedianFinder() { maxHeap = new PriorityQueue<>(Collections.reverseOrder()); minHeap = new PriorityQueue<>(); } public void addNum(int num) { maxHeap.add(num); minHeap.add(maxHeap.poll()); if (maxHeap.size() < minHeap.size()) { maxHeap.add(minHeap.poll()); } } public double findMedian() { if (maxHeap.size() == minHeap.size()) { return (maxHeap.peek() + minHeap.peek()) * 0.5; } else { return maxHeap.peek(); } }} addNum(int num): -SOAP 加入栈中:新元素首先添加到最大堆。 -为平衡两个堆的大小,可能将一个堆中的元素移到另一个堆。
findMedian(): -如果最大堆和最小堆大小相同,中位数是两者元素的平均值。 -否则,返回最大堆的顶元素作为中位数。
添加数字 1,2,3: -findMedian() 返回 2
添加数字 4: -findMedian() 返回 3
整个实现过程中,我们采用了以下策略:
通过以上方法,我们成功设计并实现了一个能够在线性时间内查询中位数的数据结构。无论是加数操作还是查询中位数,都能在 O(log n) 的时间复杂度内完成。这个方法在处理大规模动态数据流时表现优异,适用于需要实时中位数查询的场景。
转载地址:http://ixhqz.baihongyu.com/