网上找的很巧妙的解法:
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设置为足够大的常量呢。