解法一:对N进行排序,不同的排序方法时间复杂度不同,一般来说可以做到 O(nlgn) ,空间复杂度 O(n) ,这是最基本的方法了,不够效率比较低,而且做出了额外的排序,找出最大的K个数并不需要K和N-K们有序
解法二,对N进行partition,对2-N做一次扫描,小于N[0]的数放入A,大于N[0]的数放入B,如果B的length>K,则对 B 进行 partition, 如果 B.length < K, 则对A进行partition,找出前 (K - B.length) 个最大数。
如果N比较随机的话,这个算法的平均时间复杂度是O(nlogn),空间复杂度应该在 O(n)
比较害怕的就是碰到极端情况时候效率比较低,一个优化的方案是每次partition前把 N(0) 和 N(random) swap,在根据N(0) 来partition,保证处理各种数据的时候,都会比较平均。
假如单纯追求时间复杂度低,O(N)也是可以的。不过空间复杂度很大需要O(M),(M是N个数中最大的),其实就是扑克排序的极限,现在的机器都那么强大……
解法四:只遍历一次N,维护一个K个最大数的序列,遍历完便找到了。问题在于K的大小,如果K太大,空间复杂度是高的(也可以分组,找Y次,每次找出K/Y个最大数)。另外,每碰到一个新数,如果这个新数比序列中的最小数大,那么需要找到这个新数的出入的位置,可以采用2种思路,一是只记录最小数,每次有大于最小数的时候,循环一次找到次小数,抛弃最小数。另外一个方法是维护一个K的有序的序列,每次为新数找到应该放的位置。传说中用堆是比较好的,每次有新数的时候,更新堆ms时间复杂度是最小的。
木头你说的就是解法四