数据流中位数-堆

数据流中的中位数

https://www.nowcoder.com/practice/9be0172896bd43948f8a32fb954e1be1?tpId=13&tqId=11216&rp=4&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

'''老老实实本本分分用两个堆来实现'''
class Solution:
    def __init__(self):
        self.minNums=[] # 小根堆,其实存放的是最大的一半的数
        self.maxNums=[] # 大根堆,其实存放的是最小的一半的数
    def maxHeapInsert(self,num):
        self.maxNums.append(num) 
        i = len(self.maxNums)-1
        while i > 0 :
            if self.maxNums[i]>self.maxNums[(i-1)//2]:
                       # 堆的调整,如果加入的数大于其父节点的数,则交换位置
                t = self.maxNums[(i-1)//2]
                self.maxNums[(i-1)//2] = self.maxNums[i]
                self.maxNums[i] = t
                i = (i-1)//2 # 调整后的位置
            else: 
                break
    def maxHeapPop(self):
        t = self.maxNums[0] # 返回根节点,大根堆最大值
        self.maxNums[0] = self.maxNums[-1]
        self.maxNums.pop()
        lens = len(self.maxNums)
        i = 0
        while 2*i+1<lens:
            nexti = 2*i+1 #获得左孩子
            # 判断右孩子,选择最大的孩子节点值,交换位置
            if (nexti + 1 < lens) and self.maxNums[nexti + 1] > self.maxNums[nexti]:
                nexti +=1
            if self.maxNums[nexti]>self.maxNums[i]:
                tmp = self.maxNums[i]
                self.maxNums[i] = self.maxNums[nexti]
                self.maxNums[nexti] = tmp
                i = nexti
            else:break
        return t
    
    
    def minHeapInsert(self,num):
        self.minNums.append(num)
        lens = len(self.minNums)
        i = lens - 1
        while i > 0:
            if self.minNums[i] < self.minNums[(i - 1) // 2]:
                t = self.minNums[(i - 1) // 2]
                self.minNums[(i - 1) // 2] = self.minNums[i]
                self.minNums[i] = t
                i = (i - 1) // 2
            else:
                break
    def minHeapPop(self):
        t = self.minNums[0]
        self.minNums[0] = self.minNums[-1]
        self.minNums.pop()
        lens = len(self.minNums)
        i = 0
        while 2*i+1<lens:
            nexti = 2*i+1
            if (nexti+1<lens) and self.minNums[nexti] > self.minNums[nexti+1]:
                nexti += 1
            if self.minNums[nexti]<self.minNums[i]:
                tmp = self.minNums[i]
                self.minNums[i] = self.minNums[nexti]
                self.minNums[nexti] = tmp
                i = nexti
            else:
                break
        return t
    
    def Insert(self,num):
        if (len(self.minNums)+len(self.maxNums))&1==0:
            #长度为偶数,将大顶堆最大数放入小顶堆,也就是轮流着给堆插入值,先小后大
            if len(self.maxNums)>0 and num<self.maxNums[0]:
                self.maxHeapInsert(num)
                num = self.maxHeapPop()
            self.minHeapInsert(num)
        
        else: #总长度为奇数,将小顶堆最小数放入大顶堆
            if len(self.minNums)>0 and num>self.minNums[0]:
                self.minHeapInsert(num)
                num = self.minHeapPop()
            self.maxHeapInsert(num)
            
    def GetMedian(self):
        alllen = len(self.minNums)+len(self.maxNums)
        if alllen == 0:
            return -1
        if alllen & 1 == 1: # 总长度为奇数,小顶堆数量多1
            return self.minNums[0]
        else: # 总长度为偶数
            return (self.minNums[0]+self.maxNums[0])/2.0
        

全部评论

相关推荐

不愿透露姓名的神秘牛友
11-26 15:46
已编辑
字节国际 电商后端 24k-35k
点赞 评论 收藏
分享
评论
1
收藏
分享
牛客网
牛客企业服务