今日心情:为了找到工作我也是硬着头皮刷题了。
题目描述:
LeetCode 剑指 Offer 41. 数据流中的中位数
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
例如,
[2,3,4] 的中位数是 3
[2,3] 的中位数是 (2 + 3) / 2 = 2.5
设计一个支持以下两种操作的数据结构:
void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。
解题代码:
class MedianFinder {
Queue<Integer> GreaterQ, LessQ;
/** initialize your data structure here. */
public MedianFinder() {
//默认情况下PriorityQueue使用自然排序法,最小元素先出列
GreaterQ = new PriorityQueue<>(); //存储较大的 默认弹出最小值
LessQ = new PriorityQueue<>((x,y)->(y-x)); //存储较小的 lambda表达式弹出最大值
}
public void addNum(int num) {
if(GreaterQ.size() != LessQ.size()){
GreaterQ.add(num);
LessQ.add(GreaterQ.poll());
}else{
LessQ.add(num);
GreaterQ.add(LessQ.poll());
}
}
public double findMedian() {
if(GreaterQ.size() != LessQ.size()){
return GreaterQ.peek();
}else{
return (GreaterQ.peek()+LessQ.peek())/2.0;
}
}
}
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder obj = new MedianFinder();
* obj.addNum(num);
* double param_2 = obj.findMedian();
*/
解题思路:(直接看的题解+自己的理解和注意事项)
(1)找数据中的中位数,动态存入且保证随时能查询中位数,数据的排序结构在每次都能保证求取到中位数。选用队列中的PriorityQueue<>()实现。
(2)使用两个PriorityQueue<>(),一个用于存入较大的一半数,另一个用于存入较小的一半数。
GreaterQ = new PriorityQueue<>(); // 默认最先弹出最小值
LessQ = new PriorityQueue<>((x,y)->(y-x)); // 使用 lambda表达式 最先弹出最大值
(3)在 GreaterQ 和 LessQ 的size大小不同的情况下,说明所有数据流为奇数情况,此时将数据填入 GreaterQ 队列,然后将 最小的数poll 到 LessQ 队列中,此时中位数为GreaterQ的队顶处peek;如果在 GreaterQ 和 LessQ 的size大小相同的情况下,说明所有数据流为偶数情况,将数添加到LessQ 队列中,然后将其中最大的数 poll 到GreaterQ中,此时中位数为GreaterQ的队顶处的数与LessQ队顶处的数除以2。
小结:
主要是要想到使用PriorityQueue<>()实现动态的数据添加,以及如何进行大小数据的对分。同时注意如何poll最大值和最小值。