【Java - J - 41】数据流中的中位数

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

实现
/**
 * 一个数据流中的中位数
 *
 * 奇数:取中间
 * 偶数:中间两位的平均值
 *
 * 特性:左边总比右边小
 * ps:左,最大堆,堆顶-最大值,时间复杂度O(1)
 *    右,最小堆,堆顶-最小值,时间复杂度O(1)
 * 步骤:
 * 1.最大堆为空/x<=z堆顶,插入最大堆
 * 2.否则,插入最小堆
 * 3.最大堆.size-最小堆.size=0或1
 * 计算:
 * 1.奇数:最大堆.size>最小堆.size,取最大堆堆顶
 * 2.偶数:最大堆.size=最小堆.size,取2个堆顶/2
 */

public class C41_array_GetMedian {
    public static class Solution {

        //左-最大堆
        private static PriorityQueue<Integer> lHeap = new PriorityQueue<>(15, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1; // o1 - o2 则是小根堆 //PriorityQueue优先队列(也就是堆,默认为小根堆)
            }
        });
        //右-最小堆
        private static PriorityQueue<Integer> rHeap = new PriorityQueue<>();

        //保证lHeap.size() >=rHeap.size();

        public static void Insert(Integer num) {
            //先按大小插入 ,再调整
            if (lHeap.isEmpty() || num < lHeap.peek()) {
                lHeap.offer(num);
            } else {
                rHeap.offer(num);
            }
            //调整
            if (lHeap.size() < rHeap.size()) {
                lHeap.offer(rHeap.peek());
                rHeap.poll();
            } else if (lHeap.size() - rHeap.size() == 2) {
                rHeap.offer(lHeap.peek());
                lHeap.poll();
            }
        }
        public static Double getMedian() {
            if (lHeap.size() > rHeap.size()) {
                return new Double(lHeap.peek());
            } else {
                return new Double(lHeap.peek() + rHeap.peek()) / 2;
            }
        }
    }
}
Test
        public static void main(String[] args) {
            List<Integer> list =new ArrayList<Integer>(Arrays.asList(8,4,2,6,7,8,1));
            for (Integer num:list) {
                Insert(num);
            }
            System.out.println(new Double(getMedian()));
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值