zoukankan      html  css  js  c++  java
  • 63数据流中的中位数

    题目描述

    如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值



    如果能保证数据容器左边的数据都小于右边的数据,这样即使左右两边没有排序,也可以根据左边最大的数与右边最小的数得到中位数。

    用一个最大堆实现左边的数据容器,用一个最小堆实现右边的数据容器。
    插入效率o(logn),得到效率o(1)

    要保证数据平均分配到2个堆中,因此2个堆中的数据数目之差不能超过1.总数目偶数时插到最小堆中,奇数时插到最大堆中。
    读取的时候,奇数时,返回最小堆,偶数时,返回最大最小的平均。

     1 import java.util.Comparator;
     2 import java.util.PriorityQueue;
     3 public class Solution {
     4     private int cnt = 0;
     5     private PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
     6     private PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(15,new Comparator<Integer>(){
     7          @Override
     8         public int compare(Integer o1,Integer o2){
     9             return o2.compareTo(o1);
    10         }
    11     });
    12     
    13     public void Insert(Integer num) {
    14         if(cnt%2==0){ //insert min
    15             maxHeap.offer(num);
    16             num = maxHeap.poll();
    17             
    18             minHeap.offer(num);
    19         }
    20         else{
    21             minHeap.offer(num);
    22             num = minHeap.poll();
    23             
    24             maxHeap.offer(num);
    25         }
    26         cnt++;
    27     }
    28     public Double GetMedian() {
    29         if(cnt%2==0)
    30             return new Double((minHeap.peek()+maxHeap.peek())) /2;
    31         else 
    32             return new Double(minHeap.peek());
    33         
    34     }
    35 
    36 
    37 }



    c++:20180801

     1 class Solution {
     2     priority_queue<int, vector<int>, less<int> > small;
     3     priority_queue<int,vector<int>,greater<int>> big;
     4 public:
     5     void Insert(int num)
     6     {
     7      if (small.empty()||num<small.top())
     8          small.push(num);
     9      else
    10          big.push(num);
    11 
    12          if (small.size() == big.size()+2) {
    13              big.push(small.top());
    14              small.pop();
    15          }
    16          if(small.size()+1 == big.size()){
    17              small.push(big.top());
    18              big.pop();
    19          }
    20     }
    21 
    22     double GetMedian()
    23     { 
    24         if (big.size() == small.size())
    25             return (big.top() + small.top())/2.0;
    26         else
    27             return small.top();
    28     }
    29 
    30 };









    note:


    最大堆和最小堆是二叉堆的两种形式。

    1. 最大堆:根结点的键值是所有堆结点键值中最大者的堆。
    2. 最小堆:根结点的键值是所有堆结点键值中最小者的堆。

    主要操作(最小堆)

    插入

    只需要将节点插在二叉树的最后一个叶子结点位置,然后比较它对它父亲节点的大小,如果大则停止;如果小则交换位置,然后对父亲节点递归该过程直至根节点。复杂度为O(log(n))。
    一般来说,插入的位置可以不是最后一个叶子节点,可以作为任意中间节点的孩子节点插入,将这个叶子节点变为中间节点后,按上文所说的方法调整节点顺序以保证维持堆特性不变。

    删除

    要从堆中删除一个节点,用最后一个节点替换掉要刪除的节点,然后调整节点顺序以维持堆特性。

  • 相关阅读:
    每日一道 LeetCode (30): 买卖股票的最佳时机
    每日一道 LeetCode (29):杨辉三角 II
    每日一道 LeetCode (28):杨辉三角
    每日一道 LeetCode (27):二叉树的最小深度
    分布式协调服务之Zookeeper集群部署
    JupyterLab 交互式笔记本的安装使用
    YOLOv4: Darknet 如何于 Ubuntu 编译,及使用 Python 接口
    YOLOv4: Darknet 如何于 Docker 编译,及训练 COCO 子集
    pybind11: C++ 工程如何提供 Python 接口
    Mysql锁
  • 原文地址:https://www.cnblogs.com/zle1992/p/8302908.html
Copyright © 2011-2022 走看看