深度死灵发布,因为我有一个类似的问题,这是搜索时的第一个结果。我的直觉反应与其他回复相同,但在仔细观察后,OPs 解决方案似乎是 Fisher-Yates 的有效变体。
让我们来看一个使用 OPs 实现的例子。
假设 S = [1,2,3,4]。
第一次迭代:i === 0,j 必须等于 0。不进行任何交换。您可以跳过此循环。
第二次迭代:i === 1,j 可以为 0 或 1。
[1,2,3,4] (j === 1, no swap so same as original),
[2,1,3,4] (j === 0, swap),
请注意,[0-1] 导致 0,1 的所有变化的概率相等
第三次迭代:i === 2,j 可以等于 0,1,2。
[1,2,3,4], [2,1,3,4] (j === 2, no swap so same as previous results),
[1,3,2,4], [2,3,1,4] (j === 1, swaps),
[3,2,1,4], [3,1,2,4] (j === 0, swaps),
请注意,[0-2] 导致 0,1,2 的所有变化的概率相等
第四次迭代:i === 3,j 可以等于 0,1,2,3。
[1,2,3,4], [2,1,3,4], [1,3,2,4], [2,3,1,4], [3,2,1,4], [3,1,2,4] (j === 3, no swap so same as previous results),
[1,2,4,3], [2,1,4,3], [1,3,4,2], [2,3,4,1], [3,2,4,1], [3,1,4,2] (j === 2, swaps),
[1,4,3,2], [2,4,3,1], [1,4,2,3], [2,4,1,3], [3,4,1,2], [3,4,2,1] (j === 1, swaps),
[4,2,3,1], [4,1,3,2], [4,3,2,1], [4,3,1,2], [4,2,1,3], [4,1,2,3] (j === 0, swaps),
再次注意这里的结果是字符串的所有排列等概率!
这个工作的原因与链接维基中描述的“现代算法”非常相似
for i from n−1 down to 1 do
j ← random integer such that 0 ≤ j ≤ i
exchange a[j] and a[i]
Op 对每个元素执行相同的操作(j 设置在 0 和 i 之间),并以相反的方向循环。每个元素的交换是先完成还是最后完成都不会改变结果。
OPs 实现和 Fisher Yates 都共享@leeor 发布的推理陷阱。即使元素被交换的概率越来越小,但每个元素被交换到每个位置的概率相等,从而为我们提供了所需的结果。