前言:
不能因现实复杂而放弃梦想,不能因理想遥远而放弃追求”,因为——“历史只会眷顾坚定者、奋进者、搏击者,而不会等待犹豫者、懈怠者、畏难者。"
题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
解题思路
这道题我是使用优先队列来使用。分别使用一个大顶堆和小顶堆进行保存数据。这样直接说可能不会懂。举个例子来说一下思路吧。
需要求的是中位数,如果我将 1 2 3 4 5 6 7 8定为最终的数据流
此时的中位数是4+5求均值。为什么是4,为什么是5
利用队列我们就可以看得很清楚,4是前半部分最大的值,肯定是维系在大顶堆
而5是后半部分的最小值,肯定是维系在小顶堆。
所以问题就解决了:
使用小顶堆存大数据,使用大顶堆存小数据。这样堆顶取出就是中位数了。
代码样例
package com.asong.leetcode.GetMedian;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
/**
* 数据流中的中位数
* 题目描述:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,
* 那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,
* 那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,
* 使用GetMedian()方法获取当前读取数据的中位数。
*/
public class Solution {
//大顶堆存储小数据
private PriorityQueue<Integer> low = new PriorityQueue<Integer>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
//小顶堆存储大数据
private PriorityQueue<Integer> high = new PriorityQueue<Integer>();
//奇偶个数判断
private int n = 0;
public void Insert(Integer num) {
//偶数
if(n%2==0)
{
low.add(num);
high.add(low.poll());
}else {
high.add(num);
low.add(high.poll());
}
n++;
}
public Double GetMedian() {
if(n%2==0)
{
return ((low.peek()+high.peek())/2.0);
}else {
return (double)high.peek();
}
}
public static void main(String[] args) {
Solution solution = new Solution();
solution.Insert(1);
solution.Insert(2);
solution.Insert(3);
}
}