zoukankan      html  css  js  c++  java
  • 剑指offer 63.数据流中的中位数

     63.数据流中的中位数

    题目描述

    如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

    思路一:

    思路链接:https://www.nowcoder.com/questionTerminal/9be0172896bd43948f8a32fb954e1be1?answerType=1&f=discussion
    需要求的是中位数,如果我将 1 2 3 4 5 6 7 8定为最终的数据流
    此时的中位数是4+5求均值。为什么是4,为什么是5
    利用队列我们就可以看得很清楚,4是前半部分最大的值,肯定是维系在大顶堆
    而5是后半部分的最小值,肯定是维系在小顶堆。
    问题就好理解了:
    使用小顶堆存大数据,使用大顶堆存小数据。这样堆顶一取出就是中位数了。
    通过对计数器分奇偶插入不同的堆中,维护两个堆中的数据元素个数为总个数的一半或总个数的一半加一
     1 import java.util.PriorityQueue;
     2 import java.util.Comparator;
     3 public class Solution {
     4    // 两个堆,一个用来存储前半段数据的最大堆,一个用来存储后半段数据的最小堆
     5     // 优先队列默认是最小堆
     6     PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
     7     // 最大堆必须自定义比较器
     8     PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(new Comparator<Integer>(){
     9        public int compare(Integer o1, Integer o2){
    10            return o2 - o1;
    11        } 
    12     });
    13     
    14      public int count = 0;
    15  
    16     public void Insert(Integer num) {
    17         // 每插入一个元素,更新计数器,保证两个堆中的元素个数之差不超过1
    18         count++;
    19         // 如果计数器的值为奇数,插入到最小堆,然后将最小堆中的堆顶元素取出插入到最大堆
    20         if((count & 1) == 1){
    21             minHeap.offer(num);
    22             Integer max = minHeap.peek();
    23             minHeap.poll();
    24             maxHeap.offer(max);
    25         }else{    // 如果计数器为偶数,将数据插入到最大堆,然后取出最大堆的堆顶元素插入到最小堆
    26             maxHeap.offer(num);
    27             Integer min = maxHeap.peek();
    28             maxHeap.poll();
    29             minHeap.offer(min);
    30         }
    31     }
    32 
    33     public Double GetMedian() {
    34         // 判断当前元素个数,如果为奇数则取出最大堆的堆顶元素
    35         if((count & 1) == 1){
    36             return maxHeap.peek() * 1.0;
    37         }else{    // // 如果为偶数,则将两个堆的堆顶元素取出后取平均
    38             return (maxHeap.peek() + minHeap.peek()) / 2.0;
    39         }
    40         
    41     }
    42 }

    思路二:

    存入一个 列表中,取数据的时候先对列表排序,然后判断奇偶输出

     1 import java.util.ArrayList;
     2 import java.util.Collections;
     3 public class Solution {
     4     // 将数据读入到一个数组中
     5     public ArrayList<Integer> list = new ArrayList<>();
     6     public void Insert(Integer num) {
     7        list.add(num);
     8     }
     9 
    10     public Double GetMedian() {
    11         // 先对list进行排序
    12         Collections.sort(list);
    13         int size = list.size();
    14         if((size % 2) == 0){
    15             return (list.get(size / 2 - 1) + list.get(size / 2)) * 1.0  / 2.0;
    16         }else{
    17             return list.get(size / 2) * 1.0;
    18         }
    19     }
    20 }
  • 相关阅读:
    实时控制软件第四周作业
    实时控制软件第三次作业-编程作业(更新梯形加速并绘制轨迹)
    实时控制软件第三次作业(编程作业)-更新中
    实时控制软件设计第二周作业-停车场门禁控制系统状态机
    冰球游戏开发日志(四)
    冰球游戏开发日志(三)
    冰球项目开发日志(二)
    冰球项目开发日志(一)
    第四周作业
    第三周作业
  • 原文地址:https://www.cnblogs.com/hi3254014978/p/12650319.html
Copyright © 2011-2022 走看看