📜  整数流中的中位数(运行整数)(1)

📅  最后修改于: 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])
复杂度分析
  • 时间复杂度:向堆中插入元素的时间复杂度为 O(logn),故 addNum() 方法的时间复杂度为 O(logn)。同时,查找中位数需要取出堆顶元素,时间复杂度为 O(1),故 findMedian() 方法的时间复杂度为 O(1)。
  • 空间复杂度:整数流中的元素数量为 n,因此需要维护两个堆来分别存放较小和较大的一半数字,所以空间复杂度为 O(n)。
采用二分查找的方法
思路

采用二分查找的方法,需要实时维护整数流的有序数组 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
复杂度分析
  • 时间复杂度:在二分查找过程中,需要 O(logn) 的时间复杂度找到元素的插入位置,故 addNum() 方法的时间复杂度为 O(nlogn)。同时,查找中位数需要了解数组元素的个数,时间复杂度为 O(1),故 findMedian() 方法的时间复杂度为 O(1)。
  • 空间复杂度:整数流中的元素数量为 n,因此需要维护有序数组 arr,所以空间复杂度为 O(n)。