@ 剑指offer(python)数据流中的中位数

剑指offer刷题笔记63(python)

题目描述

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

思路

利用两个对来实现,一个大顶堆(利用取相反数来实现),一个小顶堆
大顶堆用来存较小的数,从大到小排列;小顶堆存较大的数,从小到大的顺序排序,中位数就是小顶堆和大顶堆的堆顶元素的平均值(有偶数个数据的时候),或者是大顶堆的堆顶元素(有奇数个数据的时候)。

具体实现

当读取数据的时候,先将数据取相反数插入大顶堆中,再将大顶堆的堆顶元素取相反数插入小顶堆中。进行完这一步操作之后,如果小顶堆的元素个数多于大顶堆的元素个数(即插入元素之后,所有的元素一共有奇数个)再把小顶堆的堆顶元素取相反数插入大顶堆中。如果小顶堆的元素个数等于大顶堆的元素个数(即当前元素的个数为偶数个),不再进行元素的变动。
获取元素的中位数:利用小顶堆和大顶堆的元素个数来判断元素有奇数个还是偶数个(大顶堆和小顶堆的元素个数相等,偶数,大顶堆的元素个数多,奇数)。当有偶数个元素时,返回小顶堆和大顶堆堆顶元素的均值(别忘了大顶堆元素的负号),有奇数元素时,返回大顶堆的堆顶元素即可。

代码

# -*- coding:utf-8 -*-
from heapq import *    # 利用python的heapq库,来实现堆
class Solution:
    def __init__(self):
        self.small = []
        self.large = []
    def Insert(self, num):
        # write code here
        small,large = self.small,self.large
        heappush(small,-heappushpop(large,-num))
        if len(large) < len(small): 
        # 这样就保持了大顶堆和小顶堆元素个数的相对稳定性,在取中位数的时候也方便。
            heappush(large,-heappop(small))
    def GetMedian(self,n=1):    
        # write code here
        small,large = self.small,self.large
        if len(large) > len(small):
            return float(-large[0])
        return (small[0] - large[0]) / 2.0
牛客python有个bug,在定义GetMedian函数的时候,加一个变量即可,要不然会显示缺参数。

你可能感兴趣的:(剑指offer(python))