📅  最后修改于: 2023-12-03 14:55:01.763000             🧑  作者: Mango
在一个整数流中,求出其中的中位数是一个常见的问题。中位数是指在一组有序的数字中,位于中间位置的数字。如果数字的个数是偶数,则中位数是中间两个数字的平均值。
例如,对于整数流 [2, 3, 4, 6, 8],中位数为 4。而对于整数流 [2, 3, 4, 6, 8, 9],中位数为 (4+6)/2=5。
本文将介绍两种求解整数流中的中位数的方法。一种采用堆,时间复杂度为 O(logn);另一种是采用二分查找,时间复杂度为 O(n)。两种方法都有相应的优点和适用场景。
采用堆的方法,需要维护整数流的两个堆,一个小根堆和一个大根堆。小根堆存放较大的一半数字,大根堆存放较小的一半数字。那么,中位数就由两个堆的堆顶元素共同确定。
为了保持两个堆尽可能平衡,对于加入整数流的元素,需要通过比较大小,插入到合适的堆中,并且需要保证两个堆的元素数量之差不超过 1。
import heapq
class MedianFinder:
def __init__(self):
self.small = [] # 小根堆
self.large = [] # 大根堆
def addNum(self, num: int) -> None:
if len(self.small) == len(self.large):
heapq.heappush(self.large, -heapq.heappushpop(self.small, -num))
else:
heapq.heappush(self.small, -heapq.heappushpop(self.large, num))
def findMedian(self) -> float:
if len(self.small) == len(self.large):
return (self.large[0] - self.small[0]) / 2.0
else:
return float(self.large[0])
采用二分查找的方法,需要实时维护整数流的有序数组 arr。对于每个输入的数字,可以通过二分查找找到它在 arr 中应该插入的位置,然后通过插入操作将其插入数组 arr 中,之后再根据数组元素的数量分别判断中位数的取值。
class MedianFinder:
def __init__(self):
self.arr = []
def addNum(self, num: int) -> None:
left, right = 0, len(self.arr) - 1
while left <= right:
mid = (left + right) // 2
if self.arr[mid] < num:
left = mid + 1
else:
right = mid - 1
self.arr.insert(left, num)
def findMedian(self) -> float:
n = len(self.arr)
if n % 2:
return self.arr[n//2]
else:
return (self.arr[n//2-1] + self.arr[n//2]) / 2.0