leetcode上做到这题:
给你一个整数数组 nums ,设计算法来打乱一个没有重复元素的数组。
实现 Solution class:
Solution(int[] nums) 使用整数数组 nums 初始化对象
int[] reset() 重设数组到它的初始状态并返回
int[] shuffle() 返回数组随机打乱后的结果输入
[“Solution”, “shuffle”, “reset”, “shuffle”]
[[[1, 2, 3]], [], [], []]
输出
[null, [3, 1, 2], [1, 2, 3], [1, 3, 2]]
答案
class Solution {
// 洗牌算法
private nums: number[]
private initNums: number[]
constructor(nums: number[]) {
this.nums = [...nums]
this.initNums = [...nums]
}
reset(): number[] {
this.nums = [...this.initNums]
return this.nums
}
shuffle(): number[] {
for (let i = 0; i < this.nums.length; ++i) {
const j = Math.floor(Math.random() * (this.nums.length - i)) + i;
const temp = this.nums[i];
this.nums[i] = this.nums[j];
this.nums[j] = temp;
}
return this.nums;
}
}
/**
* Your Solution object will be instantiated and called as such:
* var obj = new Solution(nums)
* var param_1 = obj.reset()
* var param_2 = obj.shuffle()
*/
虽然知道是洗牌算法
但是有一些细节还是想掰一掰
Math.random()
生成[0,1)左闭右开的随机小数
生成[0,n)的随机数
Math.floor(Math.random() * n)
生成[0,n]的随机数
Math.floor(Math.random() * (n + 1))
生成[m,n)的随机数
Math.floor(Math.random() * (n - m) ) + m
Fisher-Yates 洗牌算法
const arr: number[] = [1, 2, 3, 4, 5]
const map: Map<string, number> = new Map()
/**
* 获取[m,n)中的 随机整数
* @param m
* @param n
*/
const getRandomNum = (m: number, n: number): number => {
return (Math.random() * (n - m) + m) >> 0
// 等价于👇🏻
// return Math.floor(Math.random() * (n - m) + m)
}
/**
* Fisher-Yates 洗牌算法
* @param arr
* @returns arr
*/
const fisherYates = (arr: number[]): number[] => {
const n: number = arr.length
for (let i = 0; i < n; ++i) {
// 从[i,n - 1]中随机取一个索引,和第i个交换
// => 从[i,n)中随机取一个索引,和第i个交换
const index: number = getRandomNum(i, n)
const temp = arr[i]
arr[i] = arr[index]
arr[index] = temp
}
return arr
}
/**
* 验证
* 1 2 3 4 5的全排列有5! = 120种
* 次数: 120 出现: 71种
* 次数: 240 出现: 109种
* 次数: 360 出现: 117种
* 次数: 480 出现: 118种
* 次数: 600 出现: 119种
* 次数: 720 出现: 120种
* 次数: 840 出现: 120种
* 次数: 960 出现: 120种
*
* 结论: 均匀
*/
for(let i = 0;i<960;i++){
const s: string = fisherYates(arr).join('')
map.set(s,(map.get(s) || 0) + 1)
}
console.log(`map: =>`, map)