刷题笔记45——最小的K个数(TopK问题最全的5种解法)

文章目录

  • 题目描述
    • 解法1:直接排序,然后返回
    • 解法2:原地构造大根堆
    • 解法3:STL实现
    • 解法4:基于时间复杂度为O(N)的partition方法
    • 解法5:不修改数组且适合海量数据的红黑树方法O(nlogk)
  • 总结

题目描述

牛客网
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

解法1:直接排序,然后返回

最暴力,排序后前k个数就是最小的k个数,时间复杂度为O(nlogn)
刷题笔记45——最小的K个数(TopK问题最全的5种解法)_第1张图片

解法2:原地构造大根堆

这里只对前K个数构建大根堆,于是初始化建堆的时间复杂度为O(k),排序重建堆的时间复杂度为nlog(k),所以总的时间复杂度为O(k+nlogk)=O(nlogk)
刷题笔记45——最小的K个数(TopK问题最全的5种解法)_第2张图片

解法3:STL实现

将前K个数依次放入大根堆中,从第K个数开始,只要堆顶的最大元素比第i个数大,就交换,然后重新对这K个数建大根堆。对于input[i],其实变不变已经无所谓了(如果不修改,则原始数据不会改变)。
这里需要的空间复杂度是O(k)的
刷题笔记45——最小的K个数(TopK问题最全的5种解法)_第3张图片

解法4:基于时间复杂度为O(N)的partition方法

基于数组的第k个数字来调整,使得比第k个数字小的所有数字都位于数组的左边,比第k个数字大的数都位于数组的右边。这样,数组中左边的k个数字就是最小的k个数字(这k个数不一定是排序的)
刷题笔记45——最小的K个数(TopK问题最全的5种解法)_第4张图片
另外给出双向partition的实现
刷题笔记45——最小的K个数(TopK问题最全的5种解法)_第5张图片

解法5:不修改数组且适合海量数据的红黑树方法O(nlogk)

虽然它比partition方法慢,但是它不会修改数据,每次只是从原始数据中读入,所有的写操作都是在另一个容器中进行的,而且该算法适合海量数据的输入,由于内存的大小是有限的,有可能不把这些海量数据一次性全部载入内存。此时就可以从辅助存储空间(如硬盘)中每次读入一个数据,调用solution方法来判断是否需要放入返回值中即可,这种思路只要求内存能够容纳返回的数组即可,最适合n很大且k较小的问题。
刷题笔记45——最小的K个数(TopK问题最全的5种解法)_第6张图片

总结

所以,由于这些方法具有各自的优点,适用于不同的场合,所以要先问清楚题目的要求,包括输入的数据量有多大、能否一次性装入内存、是否允许交换输入数据中数字的顺序等

你可能感兴趣的:(刷题)