剑指offer——数据流中的中位数
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
自己的想法是利用二叉搜索树,将插入进来的数据流放入一个TreeSet中,这样就是一个有顺序的树,所以在需要中位数时,直接找出它的中间位置的一个(或两个)值即可
其中涉及到了利用迭代器遍历Set
还有强制类型转换,int转成double最好是基本数据类型,而不用其包装类
import java.util.TreeSet; import java.util.Iterator; public class Solution { TreeSet<Integer> numbers = new TreeSet<>(); public void Insert(Integer num) { numbers.add(num); } public Double GetMedian() { if(numbers.size() % 2 != 0){ int index = 0; for(Integer num : numbers){ if(index++ == (int)(numbers.size()/2)) return (double)num; } }else{ int index = 0; Iterator<Integer> iterator = numbers.iterator(); while(iterator.hasNext()){ if(index++ == (int)(numbers.size()/2 - 1)){ Double sum = (double)(iterator.next() + iterator.next()); return sum / 2; } iterator.next(); } } return 0.0; } }
看到其他人的做法:利用的是堆,一个大根堆(maxHeap),一个小根堆(minHeap)
然后大根堆中放的是数据中较小的一半,小根堆中放的是数据中较大的一半。
当插入元素时,如果是第奇数个,应该插在大根堆中,但是要先插入到小根堆中,然后把小根堆堆顶的元素弹出放到大根堆中。
如果是第偶数个,那么应该插在小根堆中,但是要先插入到大根堆中,把大根堆堆顶的元素弹出放到小根堆中。
当要输出中位数时,如果是偶数个,就在大根堆和小根堆中各取出堆定的那一个即可,
如果是奇数个,就直接取出大根堆的堆定即可。
当插入元素