剑指 Offer 41. 数据流中的中位数
题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
解答
class MedianFinder {
/**
解题思路:给定一长度为N的无序数组,其中位数的计算方法:首先对数组执行排序(使用O(NlogN)时间),
然后返回中间元素即可(使用O(1)时间)
结果超出时间限制
*/
/** initialize your data structure here. */
/*
LinkedList<Integer> ll = null;
public MedianFinder() {
ll = new LinkedList<Integer>();
}
*/
/**
折半插入
使用二分查找找到应该插入的位置
当low > high时折半查找停止,如果此时low <= ll.size()-1,应将[low,ll.size()-1]的元素全部后移,并将num复制到low所指位置
当ll.get(mid) == num,为了保证算法的”稳定性“,应继续在mid所指位置右边寻找插入位置
当low > high时折半查找停止,如果此时 low >= ll.size,则将num复制到low所指的位置
*/
/*
public void addNum(int num) {
int low,high,mid;
low = 0;
high = ll.size() - 1;
while(low <= high){
mid = (low + high) / 2;
if(ll.get(mid) > num){
high = mid - 1;
}else{
low = mid + 1;
}
}
if(low <= ll.size()-1){
ll.add(num);
int j = ll.size()-1;
while(j > low){
ll.set(j,ll.get(j-1));
j--;
}
ll.set(j,num);
}else{
ll.add(num);
}
for(Integer i:ll){
System.out.print(i + " ");
}
System.out.println();
}
public double findMedian() {
int length = ll.size();
int mid = length / 2;
if(length%2 != 0){
return ll.get(mid);
}else{
return (ll.get(mid) + ll.get(mid-1))/2.0;
}
}
*/
/**
解题思路:
建立一个 小顶堆A 和 大顶堆B,各保存列表的一半元素,且规定:
A保存 较大 的一半,长度为N/2(N为偶数)或(N+1)/2(N为奇数)
B保存 较小 的一半,长度为N/2(N为偶数)或(N-1)/2(N为奇数)
随后,中位数可仅根据A,B的堆顶元素计算得到
算法流程:
设元素总数为N = m + n,其中m和n分别为A和B中的元素个数
addNum(num):
当m = n(即N为偶数):需向A添加元素。实现方法:将新元素num插入至B,在将B堆顶元素插入至A
当m ≠ n(即N为奇数):需向B添加元素。实现方法:将新元素num插入至A,再将A堆顶元素插入至B
findMedian()函数:
当 m = n:中位数为A 和 B的堆顶元素之和除以2
当 m ≠ n:中位数为A的堆顶元素
*/
/** initialize your data structure here. */
PriorityQueue<Integer> minHeap = null;
PriorityQueue<Integer> maxHeap = null;
public MedianFinder() {
minHeap = new PriorityQueue(new Comparator<Integer>(){
public int compare(Integer a,Integer b){
return a - b;
}
});
maxHeap = new PriorityQueue(new Comparator<Integer>(){
public int compare(Integer a,Integer b){
return b - a;
}
});
}
public void addNum(int num) {
if(minHeap.size() == maxHeap.size()){
maxHeap.offer(num);
minHeap.offer(maxHeap.poll());
}else{
minHeap.offer(num);
maxHeap.offer(minHeap.poll());
}
}
public double findMedian() {
if(minHeap.size() == maxHeap.size()){
return (minHeap.peek() + maxHeap.peek()) / 2.0;
}else{
return minHeap.peek();
}
}
}
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder obj = new MedianFinder();
* obj.addNum(num);
* double param_2 = obj.findMedian();
*/