Algorithm 生成范围为(1,n)但不在列表(i,j)中的数字
如何生成一个范围在Algorithm 生成范围为(1,n)但不在列表(i,j)中的数字,algorithm,math,random,Algorithm,Math,Random,如何生成一个范围在(1,n)但不在某个列表中的随机数(I,j) 示例:范围是(1500),列表是[1,3,4,45199212344] 注意:列表可能无法排序 一种方法是拒绝抽样: 生成范围(1500)内的数字x x是否在您的不允许值列表中?(可以为此检查使用哈希集。) 如果是,则返回步骤1 如果否,x是您的随机值,完成 如果您的允许值集明显大于您的不允许值集,这将很好地工作:如果存在G可能的好值和B可能的坏值,那么您必须从G+B值中采样x的预期次数是(G+B)/G(相关几何分布的期望值)。
(1,n)
但不在某个列表中的随机数(I,j)
示例:范围是(1500)
,列表是[1,3,4,45199212344]
注意:列表可能无法排序
一种方法是拒绝抽样:
x
x
是否在您的不允许值列表中?(可以为此检查使用哈希集。)
- 如果是,则返回步骤1
- 如果否,
是您的随机值,完成x
如果存在
G
可能的好值和B
可能的坏值,那么您必须从G+B
值中采样x
的预期次数是(G+B)/G
(相关几何分布的期望值)。(您可以感觉检查此项。当G
变为无穷大时,期望值变为1。当B
变为无穷大时,期望值变为无穷大。)
抽样
另一种方法是列出所有允许值的
L
,然后采样L[rand(L.count)]
我假设您知道如何在[1,n]中生成一个随机数,并且您的列表的顺序与上面的示例类似
假设您有一个包含k个元素的列表。制作一个映射(O(logn))结构,如果k变高,它将确保速度。将列表中的所有元素放入映射中,其中元素值将是键,“good”值将是值。稍后我将解释“good”值。因此,当我们有了映射时,只需在[1,n-k-p]中找到一个随机数即可(稍后我将解释什么是p)如果这个数字在地图中,那么用“好”值替换它
“GOOD”value->让我们从第k个元素开始。它的GOOD value是它自己的值+1,因为下一个元素对我们来说是“GOOD”。现在让我们看看第k-1个元素。我们假设它的GOOD value也是它自己的值+1。如果这个值等于第k个元素,那么第k-1个元素的“GOOD”值就是第k个“GOOD”值+1。您还必须存储最大的“良好”值。如果最大值超过n,则p(从上面)将是p=最大-n
当然,只有当k是一个大数字时,我才建议你这样做,否则@Timothy Shields的方法是完美的。当列表长度为1时,我通常使用的技术是生成一个随机数
[1,n-1]
中的整数r
,如果r
大于或等于该单个值
值,然后递增r
这可以概括为长度k
列表中的小k
,但需要
对该列表进行排序(不能按随机顺序进行比较和递增)。如果列表长度适中,则排序后可以从b搜索开始,将跳过的值的数量添加到r
,然后递归到列表的其余部分
对于长度k
的列表,不包含大于或等于n-k
的值,您可以
可以进行更直接的替换:在[1,n-k]
中生成随机r
,以及
然后,如果r
等于list[i]
,则重复列表测试
然后将r
设置为n-k+i
(假设列表
为零),然后退出
如果某些列表元素位于[n-k,n]
中,则第二种方法将失败
在这一点上,我可以尝试投资一些聪明的东西,但到目前为止我所拥有的
对于k
值远小于
n
n-k
下面的非法值,另一个是其他值(可以就地完成)[1,n-k]
r
是list[i]
,则将r
设置为n-k+i
,并转至步骤5)r
在步骤3中没有更改,那么我们就完成了- 如果所有值都在下面的列表中,则不会进行排序,因为没有要排序的内容
- 如果所有值都在上面的列表中,则不会进行排序,因为没有将
移动到危险区域的情况r
- 随着
接近k
,上部(已排序)列表的最大大小将增加n
- 对于给定的
,如果上面的列表中出现的值越多(排序越大),那么在下面的列表中得到命中的机会就会减少,从而降低需要进行排序的可能性k
k
,情况变得非常糟糕,但在这种情况下,列表中允许r
进入的洞相对较少。这肯定是可以利用的
我可能会建议一些不同的东西,如果许多随机值具有相同的
需要列表和限制。我希望非法值列表不是
以前调用此函数的结果列表,因为如果
如果可能的话,拒绝采样将是最简单的,正如前面所述。但是,如果您不想使用,您可以将范围和不允许的值转换为集合并找到差异。然后,您可以从中选择一个随机值 假设您希望范围在[1,n]中,但不在[i,j]中,并且希望它们均匀分布 用Python
total = range(1,n+1)
disallowed = range(i,j+1)
allowed = list( set(total) - set(disallowed) )
return allowed[random.randrange(len(allowed))]
(请注意,这并不完全一致,因为在所有可能性中,max_rand%len(允许)!=0
,但这将以m为单位