动态求前n个最小值(最大值)
注: 由于最小值和最大值的分析过程完全相同,这里我们只讨论最小值的分析流程,最大值同理
问题描述
每次给定一个数值,询问此数值以及之前给定数值中最小的n个数
例如给定数值的顺序为:8 7 1 2 9 4,设n == 3
8:不足3个数,则答案为87:不足3个数,则答案为8 71:不足3个数,则答案为8 7 12:8 7 1 2中较小的3个数为7 1 29:8 7 1 2 9中较小的3个数为7 1 24:8 7 1 2 9 4中较小的3个数为4 1 2
暴力做法
一个最直观的方法是,每次添加新的数据后,将当前所有数据进行排序,选择较小的n个
一次排序最快也要\(O(nlogn)\),总的复杂度至少要\(O(n^2logn)\)
小根堆和大根堆
维护一个容量为n的大根堆,堆内元素代表当前最小的n个值
每次添加数值与堆顶元素进行比较,具有以下两种情况:
- 大于堆顶元素: 由于是大根堆,堆顶元素为最小的
n个数中的最大值,则此数值一定大于n个数中的其他值,即它一定不属于答案 - 小于堆顶元素:则用它取代堆顶元素则可以使得这
n个数更小
对于问题描述中所举的例子,使用大根堆的求解流程如下:
8:不足3个数,则答案为87:不足3个数,则答案为8 71:不足3个数,则答案为8 7 12:2 < 8, 则答案为7 2 19:9 > 7,则答案不变为7 2 14:4 < 7,则答案为4 2 1
总结
动态求前n个最小值使用大根堆
动态求前n个最大值使用小根堆

浙公网安备 33010602011771号