「每日LeetCode」2021年11月22日

本文最后更新于:2023年3月19日 晚上

Lt384. 打乱数组

384. 打乱数组

给你一个整数数组 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]] 解释 Solution solution = new Solution([1, 2, 3]); solution.shuffle(); // 打乱数组 [1,2,3] 并返回结果。任何 [1,2,3]的排列返回的概率应该相同。例如,返回 [3, 1, 2] solution.reset(); // 重设数组到它的初始状态 [1, 2, 3] 。返回 [1, 2, 3] solution.shuffle(); // 随机返回数组 [1, 2, 3] 打乱后的结果。例如,返回 [1, 3, 2]

提示:

  • 1 <= nums.length <= 200
  • -106 <= nums[i] <= 106
  • nums 中的所有元素都是 唯一的
  • 最多可以调用 5 * 104 次 reset 和 shuffle

思路

洗牌算法。思路是在每一个位置等概率的填每一个数。
第一个数,在 0n-1 下标中选择一个位置和第一个进行交换,概率为 1/n;
第二个数,在 1
n-1 下表中选择一个和第二个进行交换,概率为第一次没被选到且第二次被选到, (n-1)/n _ 1/(n-1) = 1/n;
第三个数,在 1~n-1 下表中选择恶一个和第二个进行交换,概率为第一、二次没被选到且第三次被选到, (n-1)/n _ (n-2) / (n-1) * 1/(n-2) = 1/n;
一直到最后都为 1/n;

解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* @param {number[]} nums
*/
var Solution = function (nums) {
this.nums = nums;
};

/**
* @return {number[]}
*/
Solution.prototype.reset = function () {
return this.nums;
};

/**
* @return {number[]}
*/
Solution.prototype.shuffle = function () {
const arr = this.nums.concat();
for (let i = 0; i < arr.length; i++) {
const random = Math.floor(Math.random() * (arr.length - i)) + i;
const temp = arr[random];
arr[random] = arr[i];
arr[i] = temp;
}
return arr;
};

/**
* 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()
*/