題目描述:
如何得到一個數據流中的中位數?如果從數據流中讀出奇數個數值,那麼中位數就是所有數值排序之後位於中間的數值。如果從數據流中讀出偶數個數值,那麼中位數就是所有數值排序之後中間兩個數的平均值。我們使用Insert()方法讀取數據流,使用GetMedian()方法獲取當前讀取數據的中位數。
題意理解:動態的求平均
例如,傳入的數據爲:[5,2,3,4,1,6,7,0,8],那麼按照要求,輸出是"5.00 3.50 3.00 3.50 3.00 3.50 4.00 3.50 4.00 "
PriorityQueue(優先隊列)
實際上是一個堆(不指定Comparator時默認爲最小堆)
優先級隊列的元素按照其自然順序進行排序,或者根據構造隊列時提供的 Comparator
進行排序
此隊列的頭 是按指定排序方式確定的最小 元素,隊列獲取操作 poll
、remove
、peek
訪問處於隊列頭的元素。
解題思路
查看別人的解析,大多采用大頂堆小頂堆(第一次接觸頂堆)
ps1:小頂堆存較大的數,從小到大的順序排序*
PriorityQueue
默認爲小頂堆
private
PriorityQueue<Integer> minHeap =
new
PriorityQueue<Integer>();
ps2:大頂堆存較小的數,從大到小的順序排序*(需重寫compare方法)
private
PriorityQueue<Integer> maxHeap =
new
PriorityQueue<Integer>(
new
Comparator<Integer>() {
@Override
public
int
compare(Integer o1, Integer o2) {
return
o2 - o1;
}
分奇偶的目的:保證這兩個堆是平衡的(即這兩個堆的數量相等或相差1),保證中位數就可以通過這兩個堆的堆頂元素獲得
step1:
⭐當數目爲奇數的時候,將這個值插入小頂堆中;
step2:
⭐將小頂堆中根節點(即最小值)插入到大頂堆中;
step3:⭐當數目爲偶數的時候,將這個值插入大頂堆中;
step4:⭐將大頂堆中根節點(即最大值)插入到小頂堆中;
step5:⭐取中位數的時候,如果當前個數爲偶數,取小兩堆根結點的平均值;如果當前個數爲奇數,取小頂堆的根節點
明確核心:1,分奇偶插入 2,插入後將堆頂元素移到另一個堆中
import java.util.PriorityQueue;
import java.util.Comparator;
public class Solution {
//小頂堆
private PriorityQueue<Integer> minHeap = new PriorityQueue<>();
//大頂堆
private PriorityQueue <Integer> maxHeap = new PriorityQueue<Integer>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
//記錄奇數偶數
int count=0;
public void Insert(Integer num) {
if(count%2==0){
maxHeap.add(num);
int temp = maxHeap.poll();
minHeap.add(temp);
}else{
minHeap.add(num);
int temp = minHeap.poll();
maxHeap.add(temp);
}
count++;
}
public Double GetMedian() {
double result;
if (count%2==0){
result =(minHeap.peek()+maxHeap.peek())/2.0;
}else {
result = minHeap.peek();
}
return result;
}
}}
鏈接:https://www.nowcoder.com/questionTerminal/9be0172896bd43948f8a32fb954e1be1?f=discussion
來源:牛客網