两个常数的卷积为多少_10809 一种错误的洗牌算法,以及乱排常数 (1)

8d617b995357f3ac580637cda36a96ce.png

  「洗牌」,或者说随机打乱一个数组中元素的顺序,是编程中的一个常见需求。标准的洗牌算法是 Fisher-Yates shuffle,用 JavaScript 实现如下:

function shuffle(A) {
    
    for (var i = A.length - 1; i > 0; i--) {
    
        var j = Math.floor(Math.random() * (i + 1));
        var t = A[i]; A[i] = A[j]; A[j] = t;
    }
}

其基本思路是,每次从未打乱的部分等可能地选一个元素,把它与未打乱部分的最后一个元素交换。

  Fisher-Yates 洗牌算法的实现十分简单,并且它可以保证均匀性,即元素的各种排列顺序出现的概率都相等。但是,很多人闭门造车地发明了一些「错误」的洗牌算法实现,它们不能保证均匀。例如,最常见的一种错误实现如下:

function shuffle(A) {
    
   for (var i = 0; i < A.length; i++) {
    
       var j = Math.floor(Math.random() * A.length);
       var t = A[i]; A[i] = A[j]; A[j] = t;
   }
}

其原理是,在第 i 次循环中,从所有元素中等可能地选一个元素,与第 i 个元素交换。这种算法的错误可以如下证明:对于一个长度为

的数组,算法创造了
个等可能的基本事件,这些事件对应于
种排列顺序。在非平凡情况下,
不能被
整除,所以各种排列顺序不可能等概率。

  另一种错误的洗牌算法是 @Lucas HC 在这篇答案中指出的:

A.sort(function() {
    
    return .5 - Math.random();
}); 

JavaScript 中数组自带的 sort 方法允许提供一个比较器,其返回值的正负号代表两个元素的大小关系。在上面的代码中,比较器返回的是 -0.5 到 0.5 之间的一个随机数,也就是说每次比较的结果是随机且均匀的。但是,基于随机比较的整个洗牌算法是不均匀的:它的各种运行结果的概率都形如

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值