【python-leetcode295-双堆】数据流的中位数

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

例如,

[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 范围内,你将如何优化你的算法?

需要明确的是:大顶堆中的元素是小顶堆里最小值取负后再加入的,因此大顶堆中(忽略负号)的元素肯定比小顶堆中的小。然后,让小顶堆的长度总是大于或等于大顶堆。因此当长度为奇数时,中位数就是小顶堆的堆首,为偶数时就是(大顶堆堆首+小顶堆堆首)/2

import heapq
class MedianFinder(object):
    def __init__(self):
        """
        initialize your data structure here.
        """
        self.len = 0
        #小顶堆
        self.minheap = []
        #大顶堆
        self.maxheap = []

    def addNum(self, num):
        """
        :type num: int
        :rtype: None
        """
        #加入一个数,长度加1
        self.len += 1
        #首先明确的是python中的heapq是小顶堆
        #heappushpop:将num放入堆中,然后弹出并返回heap的最小元素。
        #heappush:将item的值加入heap中,保持堆的不变性。
        #heappop:弹出并返回heap的最小的元素,保持堆的不变性。
        heapq.heappush(self.maxheap, -heapq.heappushpop(self.minheap, num))
        if len(self.maxheap) > len(self.minheap):
            heapq.heappush(self.minheap, -heapq.heappop(self.maxheap))
        print("小顶堆:",self.minheap)
        print("大顶堆:",self.maxheap)

    def findMedian(self):
        """
        :rtype: float
        """
        if self.len & 1 == 0:
            return (self.minheap[0] - self.maxheap[0]) / 2.0
        return self.minheap[0]

m=MedianFinder()
m.addNum(4)
print("中位数:",m.findMedian())
m.addNum(1)
print("中位数:",m.findMedian())
m.addNum(5)
print("中位数:",m.findMedian())
m.addNum(2)
print("中位数:",m.findMedian())
m.addNum(7)
print("中位数:",m.findMedian())

过程:负号只是占位用。

原文地址:https://www.cnblogs.com/xiximayou/p/12412000.html

时间: 2024-12-16 14:08:33

【python-leetcode295-双堆】数据流的中位数的相关文章

双堆求中位数

堆 堆的动态创建与删除可参考 http://www.java3z.com/cwbwebhome/article/article1/1362.html?id=4745,此处不再赘述. 双堆求中位数 算法描述: 1.创建两个堆(一个小根堆.一个大根堆),堆大小至少为给定数据个数的一半,向上取整: 2.假定变量mid用来保存中位数,取定第一个元素,赋值给mid,即作为初始的中位数: 3.依次遍历后面的每一个数据,如果比mid小,则插入大根堆:否则插入小根堆: 4.如果大根堆和小根堆上的数据个数相差为2

【Leetcode 大小堆、二分、BFPRT、二叉排序树、AVL】数据流的中位数(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) findMed

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) fi

[硕.Love Python] BinomialHeap(B堆 & 二项堆)

class Node(object):     def __init__(self, data):         self.data = data         self.child = None         self.left = None         self.right = None         self.degree = 0     def __str__(self):         return str(self.data)     __repr__ = __str_

[硕.Love Python] FibonacciHeap(F堆 & 斐波那契堆)

class Node(object):     __slots__ = [         'data', 'child', 'left', 'right',         'degree', 'parent', 'childCut',     ]     def __init__(self, data):         self.data = data         self.child = None         self.left = None         self.right

【洛谷】【堆】P1168 中位数

[题目描述:] 给出一个长度为N的非负整数序列A[i],对于所有1 ≤ k ≤ (N + 1) / 2,输出A[1], A[3], -, A[2k - 1]的中位数.即前1,3,5,--个数的中位数. [输入格式:] 输入文件median.in的第1行为一个正整数N,表示了序列长度. 第2行包含N个非负整数A[i] (A[i] ≤ 10^9). [输出格式:] 输出文件median.out包含(N + 1) / 2行,第i行为A[1], A[3], -, A[2i – 1]的中位数. 输入样例#

[LeetCode] Find Median from Data Stream 找出数据流的中位数

Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value. Examples: [2,3,4] , the median is 3 [2,3], the median is (2 + 3) / 2 = 2.5 Design a d

数据流的中位数

题目:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值. 思路:排序找中间 LinkedList<Integer> list=new LinkedList<Integer>(); public void Insert(Integer num) { if(list.size()==0||num<list.getFirst()){ list.ad

poj 3784 用堆动态求解中位数

堆真是一种简单而又神奇的数据结构,以前用它求过前kth的数,现在又可以用两个堆来动态求解中位数. 算法: 构建一个大顶堆和一个小顶堆,分别记为g和l. 假设当前中位数为mid,新读入一个数为tmp,则: 1.如果tmp < mid,则将tmp插入大顶堆,跳到步骤3. 2.如果tmp >= mid,则将tmp插入小顶堆,跳到步骤4. 3.如果大顶堆的元素个数比小顶堆多2(两个堆个数不平衡),则将mid插入小顶堆,弹出大顶堆堆顶元素为新的mid. 4.与步骤3相反,如果小顶堆的元素个数比大顶堆多2