程序员面试金典——实时中位数_

题目描述

现有一些随机生成的数字要将其依次传入,请设计一个高效算法,对于每次传入一个数字后,算出当前所有传入数字的中位数。(若传入了偶数个数字则令中位数为第n/2小的数字,n为已传入数字个数)。

给定一个int数组A,为传入的数字序列,同时给定序列大小n,请返回一个int数组,代表每次传入后的中位数。保证n小于等于1000。

测试样例:
[1,2,3,4,5,6],6
返回:[1,1,2,2,3,3]
核心思路:
            1.维护一个大顶堆,一个小顶堆,且保证两点:
                1)小顶堆里的全大于 大顶堆里的;
                2)2个堆个数的差值小于等于1
            2.当insert的数字个数为奇数时:使小顶堆个数比大顶堆多1;
              当insert的数字个数为偶数时,使大顶堆个数跟小顶堆个数一样。
            3.那么当总数字个数为奇数时,中位数就是小顶堆堆头;
                  当总数字个数为偶数时,中位数就是 2个堆堆头平均数
与剑指offer中的数据流中的中位数 题目一样。

注意,当最大堆与最小堆的元素个数相同时,因为最大堆中放的是小元素,所以这次中位数result结果为它。

又要注意,因为第一次的元素最终放入最小堆,然后两个堆依次加元素。所以最大堆的元素个数只可能小于或等于最小堆的元素个数。

当最大堆的个数比最小堆要小的时候,这个时候中位数result应该取最小堆中的元素。

import java.util.*;

public class Middle {
    public int[] getMiddle(int[] A, int n) {
        // write code here
       PriorityQueue<Integer>max = new PriorityQueue<>(15,new Comparator<Integer>() {
			public int compare(Integer integer1,Integer integer2){
				return integer2.compareTo(integer1);
			}
		});
		PriorityQueue<Integer>min =new PriorityQueue<>();
		int result[] = new int[n];
		for (int i = 0; i < result.length; i++) {
			if(i%2==1){//有偶数个
				min.offer(A[i]);
				max.offer(min.poll());
			}else {
				max.offer(A[i]);
				min.offer(max.poll());
			}
			//如果个数为奇数(i%2==0),取最大堆的,因为最大堆的是较小值
			if(!max.isEmpty()&&max.size()==min.size())
			result[i]=max.peek();
			else {
				result[i]=min.peek();
			}
		}
		return result;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值