您将获得一个大小为n的数组,其中包含任意布尔值。
返回随机TRUE值索引的最快方法是什么。
算法应该随机返回任何一个包含TRUE的索引。
答案 0 :(得分:5)
这样的事情:
int count = 0;
int index = -1;
for (int i = 0; i != n; ++i)
{
if (values[i])
{
++count;
if (unit_random <= 1.0f / count)
{
index = i;
}
}
}
因此,对于4个值,例如,您可以获得其索引的以下概率:
1: (1 / 1) * (1 / 2) * (2 / 3) * (3 / 4) = 1 / 4
2: (1 / 2) * (2 / 3) * (3 / 4) = 1 / 4
3: (1 / 3) * (3 / 4) = 1 / 4
4: 1 / 4 = 1 / 4
编辑:正如Steve Jessop指出的那样,浮点比较最终会导致非常不均匀的选择。假设unit_random
被定义为rand() / RAND_MAX
,则比较可以更改为:
typedef unsigned long long u64;
u64 product = u64(count) * rand();
if (product <= u64(RAND_MAX))
由于rand
的离散性,这不会给出完美的分布,但会更好。
答案 1 :(得分:1)
最快的解决方案 - 假设你没有在同一个数组上重复选择 - 是选择一个随机索引,如果是真的则返回它,如果不是则重复。在最好的情况下,所有条目都为真,这是O(1);在最坏的情况下,只有一个条目为真,这是O(n)(每次尝试都有1 / n几率击中唯一的真值,这意味着预期的n次尝试次数)。这并不比任何其他发布的解决方案更差。
如果您希望数组通常几乎都是假的,那么您可能想要选择另一种解决方案,因为此随机方法的运行时差异很大。
答案 2 :(得分:0)
“随机分配”意味着什么并不十分清楚。这是否意味着“有一些未知的分布”?如果是这样,让我们假设所有可能的分布是同等可能的,所以“预期分布”(如“预期值”)是统一的(所有可能分布的“平均值”)。然后任何索引都为TRUE,概率为1 / 2。因此,您的任务将成为尽快迭代数组的任务。从一开始就开始,就像通常迭代数组一样,直到遇到TRUE值。
答案 3 :(得分:0)
为了返回它,你必须首先计算True值(没有办法跳过它)并在另一个数组中累积它们的索引。在计数之后,您需要生成从0到N-1的随机整数(其中N是True值的数量)并从创建的数组中选择值。
伪pthon中的:
indices=[]
for i,val in enumerate(arr):
if val:
indices.append(i)
randi = randint(0,len(indices)-1)
return indices[randi]
答案 4 :(得分:0)
简单解决方案:如果相应的值为真,则生成可能索引的排列(1:n?)并按照排列返回索引的顺序
def randomTrue(x):
perm = randomPermute(0:len(x))
for i in perm:
if x[i]:
return i