JS实现shuffle函数

1,556 阅读1分钟

网上找的很巧妙的解法:

Array.prototype.shuffle = function() {
    return this.sort(function(a, b) {
      return Math.random() > 0.5 ? -1:1
    });
}

非常巧妙,通过随机数来控制sort函数的排序方式,以达到乱序的目的。时间复杂度是O(nlogn)

我用的也是Math.random,很快写出了一个shuffle,时间复杂度O(n):

Array.prototype.shuffle = function() {
    if(this.length <= 1) return this
    const array = this, length = this.length
    for(let i = 0; i < length; i++) {
        let temp = array[i]
        let count = Math.floor((length - 1) * Math.random())
        array[i] = array[count]
        array[count] = temp
    }
   return array
}

// 第二版
Array.prototype.shuffle = function() {
    if(this.length <= 1) return this
    const array = this, length = this.length
    for(let i = 0; i < length; i++) {
        let temp = array[i]
        let count = Math.floor(length * Math.random())
        array[i] = array[count]
        array[count] = temp
    }
   return array
}

为什么是length - 1呢,因为我一开始以为Math.ramdom的取值范围是[0,1],所以必须处理边界。 后来总感觉不对所以去mdn看了下,Math.ramdom 的真实取值范围是(0,1),也就是说不可能取到边界值,所以将 -1 去掉也就是第二版。

后面去网上看了看,他们是这种写法:

Array.prototype.shuffle = function() {
    if(this.length <= 1) return this
    const array = this, length = this.length
    for(let i = 0; i < length; i++) {
        let temp = array[i]
        let count = Math.floor((i + 1) * Math.random())
        array[i] = array[count]
        array[count] = temp
    }
   return array
}

不是特别理解为什么系数要和 i 挂钩,这样前几次换位的局限很大,并不是全局随机交换,比如i = 0 时count一定为0,那么这次循环根本没有意义,虽然当i逐渐增大时随机性也会增加,但是为什么不讲i设置为足够大的常量呢。