数据流中的中位数
难度:
标签:
题目描述
English description is not available for the problem. Please switch to Chinese.
代码结果
运行时间: 212 ms, 内存: 25.5 MB
/*
思路:虽然Java Streams不适用于这个数据流问题的高效实现,但为了演示,我们可以利用List来实现。每次添加数字后,排序整个列表,然后在查找中位数时从列表中获取中位数。这种方式在实际使用中不太高效,因为每次添加数字都需要排序。
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
class MedianFinderStream {
private List<Integer> nums;
public MedianFinderStream() {
nums = new ArrayList<>();
}
public void addNum(int num) {
nums.add(num);
nums = nums.stream().sorted().collect(Collectors.toList());
}
public double findMedian() {
int size = nums.size();
if (size % 2 == 0) {
return (nums.get(size / 2 - 1) + nums.get(size / 2)) / 2.0;
} else {
return nums.get(size / 2);
}
}
}
解释
方法:
这个解决方案使用了两个堆,一个最大堆(A)和一个最小堆(B),来维护数据流的中位数。最大堆A负责存储数据流中较小的一半,而最小堆B存储较大的一半。通过确保最大堆的大小总是等于或比最小堆多一个元素,我们可以有效地计算中位数。当添加一个新元素时,我们根据两个堆的大小来决定将其放入哪个堆,并可能需要调整堆,以保持大小的平衡。当寻找中位数时,如果两个堆的大小相同,则中位数是两个堆顶元素的平均值;如果不同,则是元素更多的堆的堆顶元素。
时间复杂度:
O(log n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在添加元素时,需要根据两个堆的当前大小来决定元素加入哪个堆?
▷🦆
在addNum方法中,为什么先将元素加入一个堆,然后再将顶部元素移动到另一个堆?这样做的目的是什么?
▷🦆
在findMedian方法中,如果两个堆的大小相同,为什么返回的中位数是两个堆顶元素的平均值?这与中位数的定义有何关系?
▷🦆
代码中使用了负数来实现最大堆(A),这种做法的具体原理是什么?
▷