Top K系列问题

相关题目

剑指offer: 最小的K个数
LeetCode: 215. 数组中的第K个最大元素

剑指offer: 最小的K个数

解法一:基于排序算法求解,会修改输入数组,时间复杂度O(nlogn)

解题思路

对于这个题目,最直观的解法就是先对这n个元素进行排序,排序后的前k个元素即为最小的k个元素,时间复杂度随排序算法的变化而变化,这里推荐使用归并排序,时间复杂度为O(nlogn)

解法二:利用快排思想,基于Partition函数求解,会修改输入数组,时间复杂度O(n)

解题思路

利用Parition函数,基于数组的第k个数字来调整,则使得比第k个数字小的所有数字都位于数组的左边,比第k个数字大的所有数字都位于数组的右边.调整完毕后,位于数组左边的k个数字即为最小的k个数字(这k个数字不一定是排序的).该算法时间复杂度为O(n),并且会修改输入数组.如果面试官要求不能修改输入数组,则只能考虑采用解法三或解法四

解法三:基于最大堆或红黑树求解,使用PriorityQueue模拟最大堆,不会修改输入数组,时间复杂度O(nlogk)

解题思路

我们可以先创建一个大小为k的数据容器来存储这最小的k个数字,接下来每次从输入的n个整数中读入一个数.如果容器中已有的数字少于k个,则直接把这次读入的整数放入容器之中;如果容器中已有k个数字了,也就是容器已满,此时我们不能再插入新的数字而是替换已有的数字.找出这已有的k个树中的最大值,然后拿这次待插入的数据和最大值进行比较,如果待插入的值比当前已有的最大值小,则用这个数替换当前已有的最大值;如果待插入的值比当前已有的最大值还要大,那么这个数不可能是最小的k个整数之一,于是我们抛弃这个整数.
因此,当容器满了之后,我们要做3件事情:一是在k个整数中找到最大数;二是有可能在这个容器中删除最大数;三是有可能要插入一个新的数字.如果用一颗二叉树来实现这个数组容器,那么我们能在O(logk)时间内实现这3步操作.因此,对于n个输入数字而言,总的时间效率就是O(nlogk).
这个数据容器可以考虑使用最大堆红黑树进行实现

解法四:基于最大堆或红黑树求解,自己实现最大堆,不会修改输入数组,时间复杂度O(nlogk)

LeetCode: 215. 数组中的第K个最大元素

参考文档

LeetCode 215. 数组中的第K个最大元素(java 实现)
12.1 数组中的第K个最大元素

你可能感兴趣的:(algorithm)