题目链接
牛客网 剑指offer - 数据流中的中位数 LeetCode 295题 - 数据流的中位数
算法思路
思路一
常规思路
- 初始化一个集合List,将元素添加到集合里
- 找中位数时,先对集合排序,然后判断集合的元素个数是奇数还是偶数;如果是奇数,直接取中间的数值,注意类型转换;如果是偶数,则求出中间两位数的和/2.0
思路二
初始化一个大顶堆和一个小顶堆
- 小顶堆:存储所有元素中较大的一半,堆顶存储的是其中最小的元素
- 大顶堆:存储所有元素中较小的一半,堆顶存储的是其中最大的元素
相当于把元素分为大小二半,取中位数时,取各自的堆顶的元素即可
如果num数值比小顶堆的堆顶元素大,则放在小顶堆 否则放在大顶堆
两个细节注意点: 当小顶堆的元素个数-大顶堆的元素个数>1时,需要平衡两者的数量。 当大顶堆的元素个数-小顶堆的元素个数>0时,需要平衡两者的数量。
平衡数量的原则:小顶堆的个数 >= 大顶堆的个数,并且不超过1
代码实现
实现一
import java.util.*;
public class Solution {
ArrayList<Integer> list = new ArrayList<>();
public void Insert(Integer num) {
list.add(num);
}
public Double GetMedian() {
Collections.sort(list);
int size = list.size();
if((size&1)==1){
return list.get(size/2).doubleValue();
}else{
int a = list.get(size/2 -1);
int b = list.get(size/2);
double avg = (a+b)/2.0;
return avg;
}
}
}
实现二
import java.util.*;
public class Solution {
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a,b)->b-a);
public void Insert(Integer num) {
if(minHeap.isEmpty() || num >= minHeap.peek()){
minHeap.offer(num);
if(minHeap.size()-maxHeap.size()>1){
maxHeap.offer(minHeap.poll());
}
}else{
maxHeap.offer(num);
if(maxHeap.size()-minHeap.size()>0){
minHeap.offer(maxHeap.poll());
}
}
}
public Double GetMedian() {
int minHeapSize = minHeap.size();
int maxHeapSize = maxHeap.size();
if(minHeapSize>maxHeapSize){
return minHeap.peek().doubleValue();
}else{
return (minHeap.peek()+maxHeap.peek())/2.0;
}
}
}
|