【剑指offer】数据流中的中位数

数据流中的中位数

本题利用堆排序思想。

首先,使用最大堆和最小堆,保证最大堆的数<最小堆的数。
每次插入和取出都需要调整堆。保持两个堆一样的结点数目,或者最小堆的结点数比最大堆多1。

建堆:
如果已经两个堆结点数目相同,放到最小堆,但如果该数小于最大堆,说明该数应该放到最大堆,插入最大堆之后取最大堆的堆顶插入到最小堆;
如果已经两个堆结点数目不同,即最大堆的数少,应该放到最大堆,但如果该数大于最小堆,说明应该放到最小堆,插入最小堆之后取最小堆的最小值插入到最大堆;

取出中位数:
如果总数为奇数个,取最小堆堆顶;
如果总数为偶数个,取两个堆顶平均值。

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.n = 0
        self.larger_heap = []
        self.smaller_heap = []
    # 最大堆插入操作:  
    def larger_heap_push(self, num):
        self.larger_heap.append(num)
        n = len(self.larger_heap)
        i = n - 1
        while i > 0:
            if self.larger_heap[i] > self.larger_heap[(i-1)//2]:
                self.larger_heap[i], self.larger_heap[(i-1)//2] = self.larger_heap[(i-1)//2], self.larger_heap[i]
                i = (i-1)//2
            else:
                break
    # 最大堆取出堆顶后调整堆:          
    def larger_heap_pop(self):
        ans = self.larger_heap[0]
        self.larger_heap[0] = self.larger_heap.pop()
        n = len(self.larger_heap)
        i = 0
        while 2 * i + 1 < n:
            son = 2 * i + 1
            if son + 1 < n and self.larger_heap[son+1] > self.larger_heap[son]:  # 先把son指向最大的儿子
                son += 1
            if self.larger_heap[i] < self.larger_heap[son]:  # 判断是否需要交换
                self.larger_heap[i], self.larger_heap[son] = self.larger_heap[son], self.larger_heap[i]
                i = son
            else:
                break
        return ans
    # 最小堆插入操作:
    def smaller_heap_push(self, num):
        self.smaller_heap.append(num)
        n = len(self.smaller_heap)
        i = n - 1
        while i > 0:
            if self.smaller_heap[i] < self.smaller_heap[(i-1)//2]:
                self.smaller_heap[i], self.smaller_heap[(i-1)//2] = self.smaller_heap[(i-1)//2], self.smaller_heap[i]
                i = (i-1)//2
            else:
                break
    # 最小堆取出堆顶后调整堆:             
    def smaller_heap_pop(self):
        ans = self.smaller_heap[0]
        self.smaller_heap[0] = self.smaller_heap.pop()
        n = len(self.smaller_heap)
        i = 0
        while 2 * i + 1 < n:
            son = 2 * i + 1
            if son + 1 < n and self.smaller_heap[son+1] < self.smaller_heap[son]:
                son += 1
            if self.smaller_heap[i] > self.smaller_heap[son]:
                self.smaller_heap[i], self.smaller_heap[son] = self.smaller_heap[son], self.smaller_heap[i]
                i = son
            else:
                break
        return ans
     
    def Insert(self, num):
        # write code here
        if (len(self.larger_heap) + len(self.smaller_heap)) % 2 == 1:
            if self.smaller_heap and num > self.smaller_heap[0]:
                self.smaller_heap_push(num)
                num = self.smaller_heap_pop()
            self.larger_heap_push(num)
        else:
            if self.larger_heap and num < self.larger_heap[0]:
                self.larger_heap_push(num)
                num = self.larger_heap_pop()
            self.smaller_heap_push(num)
         
    def GetMedian(self, n=None):
        # write code here
        n = len(self.larger_heap) + len(self.smaller_heap)
        if n % 2 == 1:
            return self.smaller_heap[0]
        else:
            return (self.smaller_heap[0] + self.larger_heap[0]) / 2.0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值