• 如何高效的从大量关键字中选择N个不同的关键字


    问题描述:

    假设有Sum=10亿个关键字,以文件形式存储,一行一个关键字。

    其中有重复的。共大约有K=1亿个不同关键字。

    现在要求从这里  随机选取 N个不同的关键字。

    注意:随机选取要考虑 关键字的频数

         N可能很小也可能很大

    请设计一个 尽量高效的算法

    ------------------------------------------------------------------------

    当前思路:

    N如果较小,就按一般方式处理

    N如果较大,可能需要判断 当前选择的关键字是否已经被选择,如果被选择过了,则需重选。这个过程的复杂度 太大

    所以要尽量避免,选择到重复的关键字。 直接思路是每次选择 一个关键字后 就将其从被选 关键字集里剔除。但这里必须保证每个关键字被选中的概率不变。

    比如 有如下关键字和对应频数

    A 2

    B 1

    C 1

    D 1

    在从这里选择两个关键字的前提下,A被选中的概率是:2/5*1+3/5*2/4=21/30 以此类推

    如果每个关键字只出现一次的话,就相对容易些,维持一个线性表,在逻辑上将这个线性表看成两部分,

    前面部分是待选关键字集,后面是已选关键字集。每次随机选择一个关键字后,就把它和后面的数据交换一下。更改rand范围即可。

    但是这里每个关键字出现的次数是不一样的。rand的设计不再那么简单

    总体上有那么几个想法

    1.保留重复判断

    1.1利用折半查找进行快速定位与判断

    对已选择的关键字集进行折半插入排序,每次选择了一个关键字后,用折半查找进行定位与判断。

    折半插入排序代价是O(N2),每次插入一个新的关键字

    折半查找代价是O(logN)。所以时间复杂度是O(N2)

    空间复杂度O(N)

    1.2利用hash进行快速判断

    有点类似与数据库cache中,页面是否已在cache里的判断。引入hash,链表等。

    假设hash使用mod(N)实现

    空间复杂度是O(N)

    时间复杂度是O(N)

    1.3保留重复判断的一个重要问题

    保留重复判断有一个非常严重的问题,假设N逼近关键字种类数。

    越到后面,随机选择到新的关键字的概率越小,需要重复随机选择的次数越多。

    故上述方法一般适用N<<K的情况。当N->K/2时,考虑取消重复判断,即需要构造随机选择

    2.取消重复判断

    难点在于随机选择的构造,也许这个构造本身的代价也是很大的。

    我想了很久,要即可行效率又不能比前面的差。

    我的想法是先计算出每个关键字被选到的概率。

    还是前面的例子A 21/30 B 1/10 C 1/10 D 1/10

    rand=rand(0,sum)sum初始为1

    然后麻烦的就是建立rand和i(关键字序号)之间的关系,这个查找过程消耗的代价也很大。

    因为每次选完一个后,都要剔除,所以使用累计概率是不妥的。只能一个个比对过去,边计算累计概率,边比对。

    概率的计算复杂度目前还没数

    后面选择的复杂度应该是O(N)的。

  • 相关阅读:
    操作MySQL数据库相关代码
    JSP(1)
    servlet(6)
    servlet(5)
    Java易错知识点(2)
    Java Web项目中解决中文乱码方法总结
    Java易错知识点(1)
    servlet(4)
    TCP协议之三次握手四次挥手
    day-4 map&filter
  • 原文地址:https://www.cnblogs.com/2010Freeze/p/2557310.html
Copyright © 2020-2023  润新知