有许多问题是关于一组元素,可以把他们分成两个部分。为了解决问题,我们会对前半部分元素的最小的元素、另一半元素的最大的一部分感兴趣。Two heaps模式就是一种有效解决这样的问题的方法。
Two heaps使用了两个堆:一个最小堆找到最小的元素,最大堆找到最大的元素。我们存储前半部分元素到最大堆种,后半部分元素到最小堆种。这样,如果我们需要计算中位数,直接可以根据这两个堆的堆顶元素就可以计算出来。
Two heaps模式适用于如下场景:
- 在Priority Queue, 日程安排(Scheduling)类似问题;
- 如果问题是我们需要找到数组中最小、最大、中位数;
https://leetcode.com/problems/find-median-from-data-stream/
看题目就知道是设计一个数据结构,解决中位数求解的问题。主要此时是中位数,也就是排序数组的中间那个数字。对于奇数元素的数组,就是中间那个数字;偶数则为中间两个数的平均数。
Brute force解决方案是可以维持一个排序的数组,这样每次插入元素的时候时间复杂度为O(N),计算中位数可以直接找到中间元素的index为O(1)。这是一种方案。
另外一个方案就是本文要介绍的Two heaps模式。我们可以设想,要找到中位数,其实就是找到一个元素,它左边的元素都小于它;右边的元素都大于它。这样这个元素就是中位数。这样就得到一个算法:
- 我们使用smaller 堆存储较小元素的部分,堆顶需要是最大值,所以是大根堆。这样我们知道该部分最大的元素;
- 使用larger堆存储较大元素的部分,堆顶需要最小元素,因此是小根堆。这样我们知道该集合的最小元素是什么;