繁体   English   中英

Javascript 字符串中的加扰字符,是否所有可能的排列都一样?

[英]Scrambling characters in Javascript string, are all possible permutations equally likely?

我目前正在研究一个简单的函数,该函数将打乱输入的字符串,其中所有可能的排列都具有相同的可能性 我的代码如下。

function scramble(s) {
    result = s.split("");
    for(var i = 0; i < s.length; i++) {
        var j = Math.floor(Math.random() * (i + 1));
        var scrambler = result[i];
        result[i] = result[j];
        result[j] = scrambler;
    }
    return result.join("");
}

到目前为止,代码似乎运行良好……但是所有可能的排列是否都一样? (我相信 Math.random 和 Math.floor,但是当我在运行时查看 i 和 j 时,我得到了奇怪的输出。)

除非我在这里有一个可怕的错误(请检查它是否有意义),否则我相信这段代码不会创建均匀分布的排列。

检查例如第一个字符保持原位的可能性 - 当 i 为 0 时,它不能被任何人替换,当 i 为 1 时,元素 0 和 1 将有 50% 的机会交换,依此类推。 所以总的来说, result[0] 将以1/2 * 2/3 * 3/4 ... n-1/n = 1/n概率留在它的位置

但是,最后一个元素留在原地的概率只是 (n-1)/n,因为您只有一次机会交换它并且您可以从整个数组中进行选择。

如果将(i+1)替换为s.length ,则可能会获得更好的分布,但最好的办法是采用已知有效的方法。 你可以从这里开始 - http://en.wikipedia.org/wiki/Random_permutation

Deep necro-posting 因为我有一个类似的问题,这是搜索时的第一个结果。 我的直觉反应与其他回复相同,但在更仔细地查看后, OPs 解决方案似乎是 Fisher-Yates 的有效变体。

让我们来看一个使用 OP 实现的示例。

假设 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),

再次注意,结果是字符串的所有排列等概率!

Fisher Yates shuffle 的比较

这样做的原因与链接维基中描述的“现代算法”非常相似

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 之间),并以相反的方向循环。 每个元素的交换是先完成还是最后完成都不会改变结果。

OP 实现和 Fisher Yates 都分享了@leeor 发布的推理陷阱。 即使元素被交换的概率越来越小,但每个元素被交换到每个位置的概率是相等的,从而得到我们想要的结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM