python 数据流中的移动平均值_LeetCode题记——295数据流的中位数

博客围绕LeetCode 295数据流的中位数问题展开,此题为面试高频难题。介绍了中位数定义,设计支持添加整数和返回中位数的操作的数据结构,给出示例。思路是用最大堆和最小堆分别存放数值小和大的元素,保证堆大小关系以求解中位数,还提及进阶优化问题。

991ded45aaca567273cbc4ee9740432d.png

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)

findMedian() -> 2

进阶:

如果数据流中所有整数都在 0 到 100 范围内,你将如何优化你的算法?

如果数据流中 99% 的整数都在 0 到 100 范围内,你将如何优化你的算法?

思路:设置最大堆 和 最小堆,
最小堆里存放的是数值大的那部分元素,
最大堆里存放的是数值小的那部分元素,
这样,就能保证最大堆的堆顶和最小堆的堆顶是数组排序后,中间位置的数
在入堆得过程中,保证最大堆的大小 是 最小堆大小 +1 ,或等于最小堆,
奇数个元素求中间数,就是最大堆的堆顶,
偶数个元素求中间数,就是最大堆 和 最小堆 堆顶的平均值
79.84% , 100.00%

代码:

class MedianFinder {
    private PriorityQueue<Integer> minHeap ;
    private PriorityQueue<Integer> maxHeap ;
    /** initialize your data structure here. */
    public MedianFinder() {
        minHeap = new PriorityQueue<>();
        // 最大堆,设置倒序比较规则
        maxHeap = new PriorityQueue<>(new Comparator<Integer>(){
            public int compare(Integer a , Integer b){
                return b.compareTo(a);
            }
        });
    }

    public void addNum(int num) {
        // 先向最小堆里加
        minHeap.offer(num);
        // 当最小堆中的元素比最大堆小时,将小的元素弹出,入最大堆,保证最大堆里存放的是数值小的元素,最小堆里是数值大的元素
        if(maxHeap.size() != 0 && minHeap.size() != 0 ){
            if(minHeap.peek() < maxHeap.peek()){
                maxHeap.offer(minHeap.poll());
            }
        }
        // 保证最大堆的大小等于最小堆或 等于最小堆 + 1
        if(maxHeap.size() > minHeap.size() + 1){
            minHeap.offer(maxHeap.poll());
        }
        if(maxHeap.size() < minHeap.size()){
            maxHeap.offer(minHeap.poll());
        }
    }

    public double findMedian() {
        // 如果最大堆的大小 是 最小堆大小 + 1 ,那么最大堆堆顶就是中间值
        if(maxHeap.size() > minHeap.size()){
            return 1.0 * maxHeap.peek();
        }
        // 否则,偶数个元素,取两者堆顶,计算平均值
        else{
            return (maxHeap.peek() + minHeap.peek()) / 2.0;
        }
    }
}

代码运行情况:

78695764f9d46dcdb3abeb5b5080b52c.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值