数据流中的中位数(剑指offer第64题)

一、题目描述

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

二、解题思路

方法一、利用list来保存读入的数据流,在利用list的sort方法排序后,再找出中位数

方法二、利用一个大顶堆和一个小顶堆,两个堆的元素数量差不能超过1,大顶堆的最大值小于小顶堆的最小值。这样,如果输入流的个数是偶数个的话,就分别取两个堆顶值再求平均值;如果是输入流是奇数个的话,就去多一个元素的那个堆的顶元素。

三、java代码


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;

/**
 *@Desc:  数据流中的中位数
 *@author: ghd
 *@Date: 2018年12月19日 下午2:11:24
 */
public class Solution_64 {
    /**
     * 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,
     * 那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,
     * 那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,
     * 使用GetMedian()方法获取当前读取数据的中位数。
     */
	
	//方法一、利用list来保存读入的数据流,在利用list的sort方法排序后,再找出中位数
	ArrayList<Integer> list = new ArrayList<Integer>();
    public void Insert_1(Integer num) {
         list.add(num);
    }
    //获取中位数
    public Double GetMedian_1() {
    	 double res = 0;
         int size = list.size();
         if(size != 0){
        	 Integer [] integers = (Integer [])list.toArray(new Integer[size]);
        	 Arrays.sort(integers);
        	 if((size & 1) == 0){    //为偶数时
        		 res = (integers[size/2-1] + integers[size/2])/2.0;    //注意数组下标0开始
        	 }else {
        		 int temp = size/2;
				res = integers[temp];
			}
         }
         return res;
    }
    
    
    //方法二、利用一个大顶堆和一个小顶堆,两个堆的元素数量差不能超过1,大顶堆的最大值小于小顶堆的最小值
    //这样,如果输入流的个数是偶数个的话,就分别取两个堆顶值再求平均值;如果是输入流是奇数个的话,就去多一个元素的那个堆的顶元素。
    PriorityQueue<Integer> minQueue = new PriorityQueue<Integer>();
    PriorityQueue<Integer> maxQueue = new PriorityQueue<Integer>(15,new Comparator<Integer>() {   //15为初始元素个数,设置比较规则
		@Override
		public int compare(Integer o1, Integer o2) {
			return o2 - o1;
		 }
	  }
   	);
    int count = 0;    //记录输入流的个数
    public void Insert_2(Integer num) {
    	count ++;
    	if((count & 1) == 0){  //输入流个数为偶数时,放到minQueue里
    		if(!maxQueue.isEmpty() && num<maxQueue.peek()){
    			maxQueue.offer(num);     //放入mixQueue之前,读入的num与maxQueue的最大值比较
    			num = maxQueue.poll();
    		}
    		minQueue.offer(num);
    	}else {
			if(!minQueue.isEmpty() && num>minQueue.peek()){
				minQueue.offer(num);
				num = minQueue.poll();
			}
			maxQueue.offer(num);
		}
    }
    public Double GetMedian_2() {
    	double res = 0;
    	if((count & 1) == 0){   //偶数个
    		res =  (minQueue.peek()+maxQueue.peek())/2.0;
    	}else {
			res =  (double)maxQueue.peek();
		}
    	return res;
    }
}


    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值