动态求前n个最小值(最大值)

注: 由于最小值和最大值的分析过程完全相同,这里我们只讨论最小值的分析流程,最大值同理

问题描述

每次给定一个数值,询问此数值以及之前给定数值中最小的n个数

例如给定数值的顺序为:8 7 1 2 9 4,设n == 3

  1. 8:不足3个数,则答案为8
  2. 7:不足3个数,则答案为8 7
  3. 1:不足3个数,则答案为8 7 1
  4. 28 7 1 2中较小的3个数为7 1 2
  5. 9: 8 7 1 2 9中较小的3个数为7 1 2
  6. 48 7 1 2 9 4中较小的3个数为4 1 2

暴力做法

一个最直观的方法是,每次添加新的数据后,将当前所有数据进行排序,选择较小的n个
一次排序最快也要\(O(nlogn)\),总的复杂度至少要\(O(n^2logn)\)

小根堆和大根堆

维护一个容量为n的大根堆,堆内元素代表当前最小的n个值
每次添加数值与堆顶元素进行比较,具有以下两种情况:

  • 大于堆顶元素: 由于是大根堆,堆顶元素为最小的n个数中的最大值,则此数值一定大于n个数中的其他值,即它一定不属于答案
  • 小于堆顶元素:则用它取代堆顶元素则可以使得这n个数更小

对于问题描述中所举的例子,使用大根堆的求解流程如下:

  1. 8:不足3个数,则答案为8
  2. 7:不足3个数,则答案为8 7
  3. 1:不足3个数,则答案为8 7 1
  4. 22 < 8, 则答案为7 2 1
  5. 9: 9 > 7,则答案不变为7 2 1
  6. 44 < 7,则答案为4 2 1

总结

动态求前n最小值使用大根堆
动态求前n最大值使用小根堆

posted @ 2022-02-06 15:22  0x7F  阅读(151)  评论(0)    收藏  举报