有很多个无序数,我们姑且假定他们各不相等,怎么挑选出其中最大的若干个数呢?
如果这个数据量很大,比如1亿个,如果所存数据是浮点型呢?我们该怎么处理呢?
分两部分,第一部分是我个人的解答,第二部分是书上的解答;
第一部分:
1,如果这个问题里的数据都是整数,这个问题利用hash映射应该很简单,就是在开辟一个数组,把原数组里的数据map到新开辟的数组里,如:原数组里有数据123,则在新开辟数组的123位置上填入1,。然后对新开辟的数组从后往前扫描,记录值为1的数组的下标。整个过程的时间复杂度O(n+k),n是原数组的大小,k是数组里最大数据的大小;空复杂度为O(k)。这种解法对空间的要求大,时间上是线性的,可以接受。
,2, 考虑到不能开辟新的空间的话,可以利用快速排序,时间复杂度n(lgn),然后取出前k个,总的复杂度为O(nlgn+k);利用优先队列,复杂度:O(nlgn);
,3,如果数据是浮点数,我们可以采用类似桶排序的思想,新开辟一个空间
图 A
书上的答案:
1,对于小数据量,快速排序或是堆排序,f复杂度O(NlgN)+O(K);选择排序,复杂度O(N*K);
2,利用快速排序的思想,把大问题化成小问题,引用原书上上的话:
总结:我们对于排序类的问题,无非三种思路,要么利用现有排序(或是对其进行改进),要么用空间换时间,要么大问题化小问题,这里结合了第一种情况和第二种情况;
3,如果数据量很大呢,比如100亿,推荐使用小顶堆;时间复杂度O(NlgN);
4, 利用线性排序的思想,空间换时间;
扩展:
懒得打字,我全拍下来,然后一个个分析吧。
题1:很明显,直接上桶排序,如图A;
题2:用空间换时间最快了,直接扫苗;也可以利用堆排序,直接获取k到m之间的数,还可以选择排序;复杂度都是O((m-k)lgN);
题3:维护一个堆最好了(小顶堆);
题4和题5 看不懂。
此题还可以扩展成为:求一个数组里第k大的数。
思路:
1 排序吧,快排/堆排,复杂度O(NlgN)+O(K);
2,空间换时间,复杂度O(N)+O(LEN);
3,选择排序,时间复杂度O(kN);
4 ,以上算法在控制空间的情况下,复杂度始终没有突破O(N),如果采用分治,类似快排的思想,第一趟数据分割后,比较中间数据左右的个数与k的大小,复杂度为O(N);
第二趟继续,复杂度为O(N/2),一直到复杂度为O(N/2^K)。总的复杂度O(2N);