zoukankan      html  css  js  c++  java
  • 17、【常见算法】topN问题

    题    目:如果在N个数中找出其中前K大的数?

    思路一:

      先对N个数进行排序,然后在取其前K大的数;(冒泡排序,快速排序等)

    思路二:

      部分排序,只排除前K大的数即可(使用选择排序进行部分排序,选择排序的时间复杂度O(N2))

    思路三:

      我可以用分治法,这有点类似快排中partition的操作。随机选一个数t,然后对整个数组进行partition,会得到两部分,前一部分的数都大于t,后一部分的数都小于t。

      如果说前一部分总数大于1000个,那就继续在前一部分进行partition寻找。如果前一部分的数小于1000个,那就在后一部分再进行partition,寻找剩下的数。

      该思路的事件复杂度为O(N):首先,partition的过程,时间是o(n)。我们在进行第一次partition的时候需要花费n,第二次partition的时候,数据量减半了,所以只要花费n/2,同理第三次的时候只要花费n/4,以此类推。而n+n/2+n/4+...显然是小于2n的,所以这个方法的渐进时间只有o(n)。

    思路四:

      当N的值过大,且内存资源有限,无法一次读取全部数据时,可以考虑分布式的实现,将数据切分,然后在多台机器上分别计算前K大的数,最后在把这些数据汇总。

    思路五:

      使用最小堆思想。即在内存中维护一个有K个数组成的最小堆;根据最小堆每一个节点都要比他的左右直接点小的性质:

      首先从N个数中取K个数构成最小堆;

      然后依次读取剩余数据,并且和堆顶元素比较大小,如果比堆顶小,则直接丢弃。如果比堆顶大,就替换堆顶,并调整最小堆;

      所有数据都处理完毕后,最小堆就是N个数中前K大的数。

      优点是:数据只需要读取一次,不会存在数据多次读写的问题;

    【思路五的C++实现】

    【待更新。。。。】

  • 相关阅读:
    js 常用正则表达式
    深度学习
    开通自动订阅功能前:输入银行业务信息
    VUE学习九,生命周期
    Setting Windows server firewall by powershell
    Install iis web server using powershell
    转 FAL[server, ARC3]: FAL archive failed Error 16401 creating standby archive log file at host
    springboot admin 监控
    二进制手指计数法
    SpringBoot集成Swagger-Bootstrap-UI
  • 原文地址:https://www.cnblogs.com/Long-w/p/9831679.html
Copyright © 2011-2022 走看看