LeetCode 295 数据流的中位数

中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。

例如,

[2,3,4] 的中位数是 3

[2,3] 的中位数是 (2 + 3) / 2 = 2.5

设计一个支持以下两种操作的数据结构:

void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。

 

示例:

addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3) 
findMedian() -> 2

 

进阶:

如果数据流中所有整数都在 0 到 100 范围内,你将如何优化你的算法?
如果数据流中 99% 的整数都在 0 到 100 范围内,你将如何优化你的算法?

 

解题思路:

两个堆。

用以下方式维护两个堆:

  1. 用于存储输入数字中较小一半的最大堆
  2. 用于存储输入数字的较大一半的最小堆

找到添加新数据以后,数据流的中位数,我们让这个新数据在大顶堆和小顶堆中都走了一遍。而为了让大顶堆的元素多 1 个,我们让从小顶堆中又拿出一个元素“送回”给大顶堆。

 

Python代码:

import heapq

class MedianFinder:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.count = 0
        self.maxheap = []
        self.minheap = []

    def addNum(self, num: int) -> None:
        self.count += 1
        heapq.heappush(self.maxheap, (-num, num))
        _, max_top = heapq.heappop(self.maxheap)
        heapq.heappush(self.minheap, max_top)

        if self.count % 2 == 1:
            min_top = heapq.heappop(self.minheap)
            heapq.heappush(self.maxheap, (-min_top, min_top))

    def findMedian(self) -> float:
        if self.count % 2 == 1:
            return self.maxheap[0][1]
        else:
            return (self.maxheap[0][1] + self.minheap[0]) / 2


# Your MedianFinder object will be instantiated and called as such:
# obj = MedianFinder()
# obj.addNum(num)
# param_2 = obj.findMedian()

 

你可能感兴趣的:(数据结构与算法,算法,数据结构,leetcode)