我正在编写一些JavaScript代码,如果该项符合某些要求,则应从画布中选择一个随机项。有不同种类的项目(圆形,三角形,正方形等),并且每种类型的项目数量通常不同。这些项目按层次排列(因此正方形可以包含几个圆圈,圆形可以包含其他圆形等等 - 它们都可以嵌套)。
现在,我选择随机项目的(原始)方法是:
这个问题是它不能很好地扩展。我经常遇到内存问题,因为递归深度太高或者项目总列表变得太大。
我正在考虑重写这段代码,以便我在遍历画布时考虑选择元素 - 但如果我不知道总共有多少元素,我不知道如何“随机”选择一个元素
有人知道如何解决这个问题吗?
答案 0 :(得分:5)
您可以在不先创建列表的情况下执行此操作(抱歉我的C伪代码)
int index = 0;
foreach (element)
{
if (element matches criteria)
{
index++;
int rand = random value in [1 index] range
if (1 == rand)
{
chosen = element;
}
}
}
数学计算结果表明,你有一个列表,其中3个元素符合标准,第一个元素将被选择的概率为:
1 * (1 - 1 / 2) * (1 - 1 / 3) = 1 * (1 / 2) * (2 / 3) = 1 / 3
选择第二个的可能性是:
(1 / 2) * (1 - 1 / 3) = (1 / 2) * (2 / 3) = 1 / 3
最后是第三个元素
1 / 3
这是正确答案。
答案 1 :(得分:5)
从max_r = -1
和rand_node = null
开始。通过树迭代。对于符合条件的每个节点:
r = random()
if r > max_r:
rand_node = node
max_r = r
最后rand_node
将是一个随机选择的节点,只需要一次迭代。
答案 2 :(得分:0)
您可以递归地执行此操作:
这将使小子树中的项目被选中的概率更高。
或者,您不需要构建列表,只需要跟踪项目数。这意味着第二次遍历树以获取所选项目,但您不需要额外的内存用于列表。