• 排序中topK那点事(转)


    问题描述:有 N (N>1000000)个数,求出其中的前K个最小的数(又被称作topK问题)。

     

    这类问题似乎是备受面试官的青睐,相信面试过互联网公司的同学都会遇到这来问题。下面由浅入深,分析一下这类问题。

     

    思路1:最基本的思路,将N个数进行完全排序,从中选出排在前K的元素即为所求。有了这个思路,我们可以选择相应的排序算法进行处理,目前来看快速排序,堆排序和归并排序都能达到O(NlogN)的时间复杂度。当然,这样的答案也是无缘offer的。

     

    思路2:可以采用数据池的思想,选择其中前K个数作为数据池,后面的N-K个数与这K个数进行比较,若小于其中的任何一个数,则进行替换。这种思路的算法复杂度是O(N*K),当答出这种算法时,似乎离offer很近了。

     

    有没有算法复杂度更低的方法呢?

     

    从思路2可以想到,剩余的N-K个数与前面K个数比较的时候,是顺序比较的,算法复杂度是K。怎么在这方面做文章呢? 采用的数据结构是堆。

     

    思路3:大根堆维护一个大小为K的数组,目前该大根堆中的元素是排名前K的数,其中根是最大的数。此后,每次从原数组中取一个元素与根进行比较,如小于根的元素,则将根元素替换并进行堆调整(下沉),即保证大根堆中的元素仍然是排名前K的数,且根元素仍然最大;否则不予处理,取下一个数组元素继续该过程。该算法的时间复杂度是O(N*logK),一般来说企业中都采用该策略处理topK问题,因为该算法不需要一次将原数组中的内容全部加载到内存中,而这正是海量数据处理必然会面临的一个关卡。如果能写出代码,offer基本搞定。

     

    还有没有更简单的算法呢?答案是肯定的。

     

    思路4:利用快速排序的分划函数找到分划位置K,则其前面的内容即为所求。该算法是一种非常有效的处理方式,时间复杂度是O(N)(证明可以参考算法导论书籍)。对于能一次加载到内存中的数组,该策略非常优秀。如果能完整写出代码,那么相信面试官会对你刮目相看的。

     

    下面,给出思路4的Python代码:

    def partition(data,start,end):
        if len(data)==1:
            return 0
        small=start
        p=small+1
        while p<=end:
            if data[p]<data[start]:
                small+=1
                data[p],data[small]=data[small],data[p]
            p+=1
        data[start],data[small]=data[small],data[start]
        return small
    
    def topk(data,k):
        if k==0:
            return None
        if len(data)<=k:
            return data
        left=0
        right=len(data)-1
        s=partition(data,left,right)
        while s+1!=k: #下标加1才能与前k的k进行比较
            if s+1>k:
                right=s-1
            if s+1<k:
                left=s+1
            s=partition(data,left,right)
        
        return data[:k]
     
  • 相关阅读:
    应用程序如何实现高级量规界面自定义?这个第三方控件很好用
    Web应用开发的透视网格如何实现本地化?一招教你轻松搞定
    这个布局助手工具,帮你快速构建美观的WinForm应用
    用于Delphi的DevExpress VCL组件——增强布局控件性能
    JS/TS生成随机姓名
    单例模式的错误用法
    Node极速开发WebSocket服务器
    Unity中实现WebSocket客户端
    解决git每次输入密码的问题
    html转md
  • 原文地址:https://www.cnblogs.com/gczr/p/7007592.html
Copyright © 2020-2023  润新知