【问题标题】:How to randomly generate a permutation P of the first n natural numbers that satisfies P[i] != i? [duplicate]如何随机生成满足 P[i] != i 的前 n 个自然数的排列 P? [复制]
【发布时间】:2017-06-12 06:41:27
【问题描述】:

我想随机生成前 n 个自然数的排列 P,并且它必须满足每个 i<nP[i] != i

我怎样才能有效地做到这一点?


我想出的第一个方法就是迭代地为每个位置随机选择合法数字。但是我发现它似乎并不能保证随机性。

例如在4个号码的情况下,如果我(随机)选择2,3作为前两个号码,那么最后两个号码的配置可以是0,11,0。如果我碰巧选择1,2 作为前两个,那么剩下的唯一可用选项是3,0,因为最后一位不能是3。所以看来1,2,3,0的概率是2,3,0,1的两倍吧?

另外一个办法就是随机生成一个排列,如果不满足条件就拒绝,但是这个时间复杂度不能保证。

【问题讨论】:

  • 你的意思是“均匀分布”。 “随机”并不是说概率相等。
  • @Henry 对,我的意思是“均匀分布”确实
  • 您可以使用Fisher-Yates Shuffle 来随机化初始序列。万一,一个元素被错误地放置,将它与它的邻居交换。如果错误放置了更多元素,请对这些元素执行第二次 Fisher-Yates shuffle。
  • 对于较大的 n,排列没有固定点的概率趋于 1/e。因此,拒绝具有固定点的排列的策略平均需要 e (2.718...) 次尝试。在无限制排列的生成过程中,如果您检测到将有一个固定点来加快处理速度,您也可以“快速失败”。所以这在实践中不应该表现得太糟糕。
  • @Henry 很高兴知道这一点,谢谢

标签: algorithm random combinations permutation


【解决方案1】:

您可以对Fisher-Yates shuffle 进行反复试验。用固定点计算排列P 的概率是1-1/e,这意味着预期的试验次数是e(或大约三个)。

这里我使用了一个已知事实,如果投掷有偏硬币时看到正面的概率是p,那么在获得第一个正面之前的预期试验次数是1/p

那么总的预期运行时间是O(n)

还请注意,这是渐近最优的,因为任何计算没有固定点的随机排列的算法都必须触及所有元素。

伪代码:

generateRandomPermutation(n)
    do
        generate a random permutation P of {1,2,3,...,n} with Fisher-Yates // O(n)
    while there exists i with P[i] = i // Expected nr of iterations is e
    return P

【讨论】:

  • @JohnColeman 啊,我误解了这个问题。我认为我们得到了一个整数i,它不能被修复(这是唯一的约束);在这种情况下,我的论点有效。如果问题是找到一个没有固定点的排列,那么可以,我们期望进行三次(实际上是e)迭代。感谢您的提醒;我更新了答案。
  • OP 的问题表述得不是很清楚,因为他们忽略了量化i。你原来的解释很合理。作为一种优化,您可以在看到固定点后立即将 Fisher-Yates 短路,但在具有内置 shuffle 的语言中,这可能不值得麻烦。
猜你喜欢
  • 2021-08-30
  • 1970-01-01
  • 1970-01-01
  • 2017-02-19
  • 2012-01-12
  • 1970-01-01
  • 1970-01-01
  • 2018-07-18
  • 1970-01-01
相关资源
最近更新 更多