牛客地址
解题思路
利用一个大顶堆maxHeap,一个小顶堆minHeap,保存元素(在添加的过程中,始终保持大顶堆中的所有元素都小于小顶堆中的元素,即maxHeap.peek() < minHeap.peek())
1. 对于吐出的每一个元素num, 如果为添加
(1) 优先考虑加入maxHeap, 加入条件是:
- maxHeap为空;
- num < maxHeap.peek();
- minHeap非空且num < minHeap.peek();
(2) 否则加入minHeap;
(3) 调整这两个堆的大小之差不能超过1, 具体过程如下:
- 如果minHeap.size() - maxHeap.size() >=2: maxHeap.offer(minHeap.poll());
- 如果maxHeap.size() - minHeap.size() >=2: minHeap.offer(maxHeap.poll());
2. 如果num表示获取中位数
- 如果minHeap的大小+maxHeap的大小为偶数,返回minHeap.peek()和maxHeap.peek()的平均值
- 否则返回size大的堆的peek()值。
实现代码
import java.util.*;
public class Solution {
/**
* the medians
* @param operations int整型二维数组 ops
* @return double浮点型一维数组
*/
private PriorityQueue<Integer> minHeap = new PriorityQueue<>();
private PriorityQueue<Integer> maxHeap = new PriorityQueue<>((o1, o2) -> (o2 - o1));
public void add(int num){
if(maxHeap.isEmpty() || num < maxHeap.peek()){
maxHeap.offer(num);
return;
}
if(!minHeap.isEmpty() && num < minHeap.peek()){
maxHeap.offer(num);
return;
}
minHeap.offer(num);
}
public void adjustTwoHeaps(){
while(minHeap.size() - maxHeap.size() >= 2){
maxHeap.offer(minHeap.poll());
}
while(maxHeap.size() - minHeap.size() >= 2){
minHeap.offer(maxHeap.poll());
}
}
public double getMediaNum(){
int minSize = minHeap.size();
int maxSize = maxHeap.size();
if(minSize == 0 && maxSize == 0){
return -1;
}
int minNum = minSize == 0 ? 0 : minHeap.peek();
int maxNum = maxSize == 0 ? 0: maxHeap.peek();
if(((minSize + maxSize) & 1) == 0){
return (minNum + maxNum) / 2.0;
}
return maxSize > minSize ? maxNum : minNum;
}
public double[] flowmedian (int[][] operations) {
// write code here
List<Double> res = new ArrayList<>();
int len = operations.length;
for(int i = 0; i < len; i++){
int operator = operations[i][0];
if(operator == 1){
add(operations[i][1]);
adjustTwoHeaps();
}
else{
res.add(getMediaNum());
}
}
double[] ans = new double[res.size()];
for(int i = 0; i < res.size(); i++){
ans[i] = res.get(i).doubleValue();
}
return ans;
}
}
解题反思
- 在add函数中调用了adjustTwoHeaps函数,可里面的逻辑会提早return ,所以很真实结果相反
- 在调整两个堆的时候,由while代替if,更符合真实逻辑
- 构造输出结果的时候,添加的值应该是Double类的doubleValue()值。
- 在判读一个数的奇偶性时,利用&1的操作