利用PriorityQueue求动态数据流中的中位数

数据流中的中位数

http://www.nowcoder.com/questionTerminal/9be0172896bd43948f8a32fb954e1be1

使用大小顶堆来进行插入时排序。

需要求的是中位数,如果我将 1 2 3 4 5 6 7 8定为最终的数据流
此时的中位数是4+5求均值。为什么是4,为什么是5
利用队列我们就可以看得很清楚,4是前半部分最大的值,肯定是维系在大顶堆
而5是后半部分的最小值,肯定是维系在小顶堆。
问题就好理解了:
使用小顶堆存大数据,使用大顶堆存小数据。这样堆顶一取出就是中位数了。

import java.util.*;

public class Solution {

    private int cnt = 0;
    //默认的小顶堆
    private PriorityQueue<Integer> low = new PriorityQueue<>();
    //重写为大顶堆
    private PriorityQueue<Integer> high = new PriorityQueue<>(new Comparator<Integer>(){
        public int compare(Integer o1, Integer o2){
            return o2.compareTo(o1);
        }
    });

    public void Insert(Integer num) {
        //数量++
        cnt++;
        if((cnt & 1) == 1){    //数据流为奇数
            if(!low.isEmpty() && num > low.peek()){    
                low.offer(num);
                //会吐出最小的数
                num = low.poll();
            }

            high.offer(num);
        }else{
            if(!high.isEmpty() && num < high.peek()){
                high.offer(num);
                //大顶堆最小的数,在小顶堆就是最大的数
                num = high.poll();
            }
            low.offer(num);
        }


    }

    public Double GetMedian() {
        double res = 0;
        if((cnt & 1) == 1){
            res = high.peek();
        }else{
            res = (high.peek() +low.peek()) / 2.0;
        }
        return res;
    }


}

其实除此之外还有其他几个思路: * 使用无序数组存储,在得到中位数前对数组进行排序。(这是最容易想到的)
import java.util.ArrayList;
import java.util.Collections;
public class Solution {
    ArrayList<Integer> array = new ArrayList<>();
    public void Insert(Integer num) {
        array.add(num);
    }

    public Double GetMedian() {
        Collections.sort(array);
        int index = array.size()/2;
        if(array.size()%2 != 0){  //奇数直接取
            return (double)array.get(index);
        }
        return ((double)(array.get(index-1))+(double)array.get(index))/2;//偶数平均值
    }
}
  • 插入时排序,不利用堆,而是利用二分法。
import java.util.LinkedList;
import java.util.List;
public class Solution {
    private List<Integer> list = new LinkedList();

    public void Insert(Integer num) {
        if(list.size()==0){
            list.add(num);
            return;
        }
        int first = 0;
        int last = list.size()-1;
        int mid = 0;
        while(first <= last){
            mid = (first+last)/2;
            if(list.get(mid)>num)
                last = mid-1;
            else
                first = mid+1;
        }
        list.add(first,num);
        return;
    }

    public Double GetMedian() {
        int index = list.size();
        if(index%2==1){
            return (double)list.get(index/2);
        }
       return ((double)(list.get(index/2-1))+(double)list.get(index/2))/2;
    }
}
全部评论

相关推荐

不愿透露姓名的神秘牛友
昨天 13:41
点赞 评论 收藏
分享
07-15 14:14
门头沟学院 Java
7.10投递7.15感谢信
投递地平线等公司8个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务