剑指offer63.数据流中的中位数

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

先排序后求解这样能过:
# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.data = []
    def Insert(self, num):
        # write code here
        self.data.append(num)
        self.data.sort()
    def GetMedian(self, data):
        # write code here
        length = len(self.data)
        return self.data[length//2] if length%2 == 1 else\
            (self.data[(length//2)-1]+self.data[(length//2)])/2.0
可以建立一个大顶堆加一个小顶堆,分别存放较小和较大数据:

当两个堆数据个数为偶数的时候,把数存入最大堆,然后重排最大堆,如果最大堆的堆顶数字大于最小堆堆顶数字,则把两个堆顶数字交换,重排两堆,此时两堆数字总数为奇数,直接输出最大堆堆顶数字即为中位数;
当两堆数据总数为奇数的时候,把数存入最小堆,重排最小堆,如果最大堆的堆顶数字大于最小堆堆顶数字,则把两个堆顶数字交换,重排两堆,此时两堆数字总数为偶数,取两堆堆顶数字做平均即为中位数。

在这里大小堆不必分别构造,构造一个另外一个变换符号即可用:
# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.small = []  # 小的数,大顶堆
        self.big = []  # 大的数,小顶堆
        self.count = 0  # 计数
    def Insert(self, num):
        # write code here
        if self.count%2 == 0:
            self.small.append(num)
        else:
            self.big.append(-num)
        self.count += 1
    def GetMedian(self, a):
        # write code here
        if self.count == 1:
            return self.small[0]
        self.maxheap(self.small)
        self.maxheap(self.big)  # 用大顶堆构建小顶堆,变符号就行
        if self.small[0] > -self.big[0]:
            self.small[0], self.big[0] = -self.big[0], -self.small[0]
        self.maxheap(self.small)
        self.maxheap(self.big)
        if self.count%2 == 1:
            return self.small[0]
        else:
            return (self.small[0]-self.big[0])/2.0

    def maxheap(self, data):  # 构建最大堆
        for start in range(len(data)//2-1, -1, -1):
            root = start
            while True:
                child = 2*root + 1
                if child >= len(data):  # 无子节点
                    break
                if child+1 < len(data) and data[child+1] > data[child]:
                    child += 1  # 找较大子节点
                if data[root] < data[child]:
                    data[root], data[child] = data[child], data[root]
                    root = child
                else:
                    break
        return data
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值