Algorithm 快速随机选择算法

Algorithm 快速随机选择算法,algorithm,random,Algorithm,Random,给定一个真/假值数组,随机选择具有真值的索引的最有效算法是什么 给出了一个简单的算法 a <- the array c <- 0 for i in a: if a[i] is true: c++ e <- random number in (0, c-1) j <- 0 for i in e: while j is false: j++ return j a建立一个包含指向true值的索引的列表,并随机选择其中一个。列表遍历需要O(n),随机数需要一次尝

给定一个真/假值数组,随机选择具有真值的索引的最有效算法是什么

给出了一个简单的算法

a <- the array
c <- 0
for i in a:
    if a[i] is true: c++
e <- random number in (0, c-1)
j <- 0
for i in e:
    while j is false: j++
return j

a建立一个包含指向
true
值的索引的列表,并随机选择其中一个。列表遍历需要O(n),随机数需要一次尝试。

使用“从无限列表中选取随机元素”算法

保留您当前选择的索引,以及您看到的真实值的数量

当您看到一个真值时,增加计数,然后用概率为p=(1/count)的当前索引替换拾取。(所以你总是选择你找到的第一个……然后你可能会切换到第二个,概率为1/2,然后你可能会切换到概率为1/3的第三个。)

这只需要对列表进行一次扫描并进行持续存储。(不过,它确实需要你计算出更多的随机数。)特别是,它不需要你缓冲列表或返回开始,因此它可以在无限的输入流上工作


请参阅简单的“拾取随机元素”算法的LINQ实现示例;它只需要稍作调整。

只是想知道,这些类型的算法在哪些应用程序中使用?前一段时间,我遇到了一个类似的问题,给定一个无限大的数组,前n位用1填充,其余都是零。现在,这个数组被提供给一个新用户(他不知道n的值)。现在找出一个算法来标记最后一个1所在的位置。我通过二进制搜索解决了这个问题。请给出一些使用这些的示例。近似重复:。在这个问题中,数组的大小是52,这可能会影响答案(例如,你很确定大小为52的arary适合内存,而
a
这里可能不适合)。这肯定比我提出的更快,尽管它使用O(n)工作空间,而我的只使用恒定的工作空间。因此,仍有改进的余地。速度肯定更快吗?如果真值非常罕见,那么它几乎肯定会更快。如果伪值非常罕见,那么几乎可以肯定它会变慢。我不知道盈亏平衡点在哪里。是的,真/假值的分布对于哪个算法更有效的问题确实很重要。但当这还不清楚的时候,所有的赌注都被取消了,就像往常一样。不过,我觉得乔恩的回答很好,而且可能会比这更好。@Steve:这取决于你需要多久做一次。构建索引只发生一次,因此即使伪值非常罕见,使用索引最终也会更快。是的,我没有想到:可能会保证在下次更改数组内容之前完成一定数量的选择。如果允许我们稍微扩大范围,那么最好完全去掉标志数组,只保留一个包含“true”索引的结构。插入/删除速度较慢,但选择速度较快。此处提供了更多详细信息和证据:。这个问题在功能上与那个问题是重复的,尽管措辞有点不同。我的直觉是,假设内存中有数据,它很可能比两次通过算法慢。但是值得测试的是,无论出于何种原因,如果两次通过的性能是不可接受的。@史蒂夫:这取决于“真”值的稀疏性与生成随机数的成本。如果你在列表中有一百万个条目,其中只有两个是“真的”,那么这很可能是一场胜利。另一方面,如果有一百万个条目都是真的,那么两次通过算法可能会更快。总的来说,我只是喜欢一次通过常数存储算法的优雅:)嘿,我只是在约翰尼斯的回答中对稀疏性做了同样的评论。我也同意优雅,尽管我有点担心使用大量随机数会使分析RNG中任何弱点的影响变得更加困难。感谢Jon和Steve,我怀疑有这样的技术,但我以前没有意识到!