剑指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