leetcode 数据流中的中位数

题目链接
思路:双 大/小根堆
分析:看中位数的定义,排序后的中间的数
如果数据流的长度是奇数,那么中位数就是中间的那个数。
如果数据流的长度是偶数,那么中位数就是中间两个数的平均数。

问题一:每次判断长度然后去找中间的一个或者两个数的复杂度是O(n),并且每次插入数字,要排序好,时间复杂度O(nlogn),如果是n个数字,那么时间复杂度就是n2logn了。这个是需要解决的问题。
解决方案:我们需要的并不是整个有序,而仅仅是需要中间两个或者一个是有序,也就是说仅仅需要保证中间两个或者一个数字在有序的位置上,那么我们可以用两个堆,一个大顶堆,一个小顶堆,前半段是大顶堆,那么顶端就是中间的元素,后半段就是小顶堆,那么顶端就是中间的元素。
当取中位数的时候,通过判断前半段和后半段的个数就可以返回中位数。
代码:

class MedianFinder {

        PriorityQueue<Integer> preQueue;
        PriorityQueue<Integer> afterQueue;

        /** initialize your data structure here. */
        public MedianFinder() {
            //大根堆
            preQueue = new PriorityQueue<>((a,b)->{return b-a;});

            //小根堆
            afterQueue = new PriorityQueue<>((a,b)->{return a-b;});
        }

        public void addNum(int num) {
            if(preQueue.isEmpty() || preQueue.peek()>num){
                //比前半段最大的小,说明num肯定在前半段
                preQueue.add(num);

                //如果前半段比后半段多两个,那么需要把前半段的元素移动一个到后半段
                if(afterQueue.size()+1<preQueue.size()){
                    afterQueue.add(preQueue.poll());
                }
            }else{
                //否则肯定在后半段
                afterQueue.add(num);

                //如果后半段比前半段多两个,那么需要把后半段的元素移动一个到前半段
                if(preQueue.size()+1 < afterQueue.size()){
                    preQueue.add(afterQueue.poll());
                }
            }
        }

        public double findMedian() {
        	//如果前半段和后半段个数一样,那么就是偶数个
            if(preQueue.size()==afterQueue.size()){
                return ((preQueue.peek()+afterQueue.peek()) * 1.0) / 2;
            }
            //否则,多的那一边的多一个数多的就是那个顶元素就是中位数
            if(preQueue.size()>afterQueue.size()){
                return preQueue.peek();
            }else{
                return afterQueue.peek();
            }
        }
}

好好学习。
不打扰是我的温柔。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值