数据流的中位数

题目描述

有一个源源不断的吐出整数的数据流,假设你有足够的空间来保存吐出的数。请设计一个名叫MedianHolder的结构,MedianHolder可以随时取得之前吐出所有数的中位数。
[要求]

  1. 如果MedianHolder已经保存了吐出的N个数,那么将一个新数加入到MedianHolder的过程,其时间复杂度是O(logN)。
  2. 取得已经吐出的N个数整体的中位数的过程,时间复杂度为O(1)

每行有一个整数opt表示操作类型
若opt=1,则接下来有一个整数N表示将N加入到结构中。
若opt=2,则表示询问当前所有数的中位数

示例1
输入:
[[1,5],[2],[1,3],[2],[1,6],[2],[1,7],[2]]
返回值:
[5,4,5,5.5]
说明:
第一次查询时结构内的数为:5
第二次查询时结构内的数为:3 5
第二次查询时结构内的数为:3 5 6
第二次查询时结构内的数为:3 5 6 7

分析
代码
import java.util.*;
public class Solution {
  /**
   * the medians
   * @param operations int整型二维数组 ops
   * @return double浮点型一维数组
   */
  class MedianHolder{

      double medianNum = -1;
      int size = 0;
      // 建立最小堆存放排序后的右边的数据,堆顶是右边数据的最小值
      PriorityQueue<Integer> right = new PriorityQueue<>();
      // 建立最大堆,存放排序后左边的数据,堆顶是左边数据的最大值
      PriorityQueue<Integer> left = 
          new PriorityQueue<>((o1,o2) -> o2 - o1);
      // 添加数据
      public void add(int num){
          // 新增一个数,总数量为变为偶数
          if(left.size() > right.size()){

              left.offer(num);
              right.offer(left.poll());
              // 更新中位数
              medianNum = (right.peek() + left.peek()) / 2.0;
              return ;
          }
          // 新增一个数,总数量变为奇数
          right.offer(num);
          left.offer(right.poll());
          medianNum = left.peek();
          return;

      }
      // 返回中值
      public double getMedian(){
          return this.medianNum;
      }
  }
  public double[] flowmedian (int[][] operations) {
      // 存储中位数
      List<Double> res = new ArrayList<>();
      MedianHolder holder = new MedianHolder();
      // 遍历命令
      for (int i = 0;i < operations.length;++i){
          if (operations[i][0] == 1){
              holder.add(operations[i][1]);
          }
          if (operations[i][0] == 2){
              res.add(holder.getMedian());
          }
      }
      double[] medians = new double[res.size()];
      for (int i = 0;i < res.size();++i){
          medians[i] = res.get(i);
      }
      return medians;
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值