随时找到数据流中的中位数

牛客地址

解题思路

利用一个大顶堆maxHeap,一个小顶堆minHeap,保存元素(在添加的过程中,始终保持大顶堆中的所有元素都小于小顶堆中的元素,即maxHeap.peek() < minHeap.peek())

1. 对于吐出的每一个元素num, 如果为添加

(1) 优先考虑加入maxHeap, 加入条件是:

  • maxHeap为空;
  • num < maxHeap.peek();
  • minHeap非空且num < minHeap.peek();

(2) 否则加入minHeap; 

(3) 调整这两个堆的大小之差不能超过1, 具体过程如下:

  • 如果minHeap.size() - maxHeap.size() >=2: maxHeap.offer(minHeap.poll());
  • 如果maxHeap.size() - minHeap.size() >=2: minHeap.offer(maxHeap.poll());

2. 如果num表示获取中位数

  • 如果minHeap的大小+maxHeap的大小为偶数,返回minHeap.peek()和maxHeap.peek()的平均值
  • 否则返回size大的堆的peek()值。

实现代码

import java.util.*;


public class Solution {
    /**
     * the medians
     * @param operations int整型二维数组 ops
     * @return double浮点型一维数组
     */
    private PriorityQueue<Integer> minHeap = new PriorityQueue<>();
    private PriorityQueue<Integer> maxHeap = new PriorityQueue<>((o1, o2) -> (o2 - o1));
    public void add(int num){
        if(maxHeap.isEmpty() || num < maxHeap.peek()){
            maxHeap.offer(num);
            return;
        }
        if(!minHeap.isEmpty() && num < minHeap.peek()){
            maxHeap.offer(num);
            return;
        }
        minHeap.offer(num);
    }
    public void adjustTwoHeaps(){
        while(minHeap.size() - maxHeap.size() >= 2){
            maxHeap.offer(minHeap.poll());
        }
        while(maxHeap.size() - minHeap.size() >= 2){
            minHeap.offer(maxHeap.poll());
        }
    }
    public double getMediaNum(){
        int minSize = minHeap.size();
        int maxSize = maxHeap.size();
        if(minSize == 0 && maxSize == 0){
            return -1;
        }
        int minNum = minSize == 0 ? 0 : minHeap.peek();
        int maxNum = maxSize == 0 ? 0: maxHeap.peek();
        if(((minSize + maxSize) & 1) == 0){
            return (minNum + maxNum) / 2.0;
        }
        return maxSize > minSize ? maxNum : minNum;
    }
    public double[] flowmedian (int[][] operations) {
        // write code here
        List<Double> res = new ArrayList<>();
        int len = operations.length;
        for(int i = 0; i < len; i++){
            int operator = operations[i][0];
            if(operator == 1){
                add(operations[i][1]);
                adjustTwoHeaps();
            }
            else{
                res.add(getMediaNum());
            }
        }
        double[] ans = new double[res.size()];
        for(int i = 0; i < res.size(); i++){
            ans[i] = res.get(i).doubleValue();
        }
        return ans;
    }
}

解题反思

  • 在add函数中调用了adjustTwoHeaps函数,可里面的逻辑会提早return ,所以很真实结果相反
  • 在调整两个堆的时候,由while代替if,更符合真实逻辑
  • 构造输出结果的时候,添加的值应该是Double类的doubleValue()值。
  • 在判读一个数的奇偶性时,利用&1的操作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值