解法一:该解法是大部分能想到的,也是第一想到的方法。假设数据量不大,可以先用快速排序或堆排序,他们的平均时间复杂度为O(N*logN),然后取出前K个,时间复杂度为O(K),总的时间复杂度为O(N*logN)+O(K).
当K=1时,上面的算法的时间复杂度也是O(N*logN),上面的算法是把整个数组都进行了排序,而原题目只要求最大的K个数,并不需要前K个数有限,也不需要后N-K个数有序。可以通过部分排序算法如选择排序和交换排序,把N个数中的前K个数排序出来,复杂度为O(N*K),选择哪一个,取决于K的大小,在K(K<logN)较小的情况下,选择部分排序。
解法二:(掌握)避免对前K个数进行排序来获取更好的性能(利用快速排序的原理)。
假设N个数存储在数组S中,从数组中随机找一个元素X,将数组分成两部分Sa和Sb.Sa中的元素大于等于X,Sb中的元素小于X。
出现如下两种情况:
(1)若Sa组的个数大于或等于K,则继续在sa分组中找取最大的K个数字 。
(2)若Sa组中的数字小于K ,其个数为T,则继续在sb中找取 K-T个数字 。
一直这样递归下去,不断把问题分解成小问题,平均时间复杂度为O(N*logK)。
代码如下:
当K=1时,上面的算法的时间复杂度也是O(N*logN),上面的算法是把整个数组都进行了排序,而原题目只要求最大的K个数,并不需要前K个数有限,也不需要后N-K个数有序。可以通过部分排序算法如选择排序和交换排序,把N个数中的前K个数排序出来,复杂度为O(N*K),选择哪一个,取决于K的大小,在K(K<logN)较小的情况下,选择部分排序。
解法二:(掌握)避免对前K个数进行排序来获取更好的性能(利用快速排序的原理)。
假设N个数存储在数组S中,从数组中随机找一个元素X,将数组分成两部分Sa和Sb.Sa中的元素大于等于X,Sb中的元素小于X。
出现如下两种情况:
(1)若Sa组的个数大于或等于K,则继续在sa分组中找取最大的K个数字 。
(2)若Sa组中的数字小于K ,其个数为T,则继续在sb中找取 K-T个数字 。
一直这样递归下去,不断把问题分解成小问题,平均时间复杂度为O(N*logK)。
代码如下: