问题: 随机播放一组没有重复的数字。
Example:
// Init an array with set 1, 2, and 3.
int[] nums = {1,2,3};
Solution solution = new Solution(nums);
// Shuffle the array [1,2,3] and return its result. Any permutation of [1,2,3] must equally likely to be returned.
solution.shuffle();
// Resets the array back to its original configuration [1,2,3].
solution.reset();
// Returns the random shuffling of array [1,2,3].
solution.shuffle();
答案:
var Solution = function(nums) {
// hold nums in Solution
this.nums = nums;
};
Solution.prototype.reset = function() {
return this.nums;
};
Solution.prototype.shuffle = function() {
// create a copy of this.nums, shuffle it, and return it0
const shuffled = this.nums.slice();
const n = shuffled.length;
const swap = (arr, i, j) => {
let tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
// swap elements with random elements
for (let i = 0; i < n; i++)
swap(shuffled, i, Math.floor(Math.random() * n));
return shuffled;
};
我的问题: 您将在Math.floor(Math.random()* n)中获得数组长度之外的随机索引。我不明白,这段代码不能重复吗?假设长度为3。则公式的索引为2,另一个索引为2,从而使索引重复。任何人都可以澄清我的误会。谢谢。 Math.random是否会自动撤回已使用的索引?
答案 0 :(得分:2)
是的,Math.floor(Math.random() * n)
表达式可以多次求值相同的数字,但是没关系,因为swap
中使用了随机数,这会切换索引i
上的数字该数字位于所选的随机索引处。
如果随机索引是从原始数组中提取并添加到要返回的数组中,例如
const randIndex = Math.floor(Math.random() * n);
arrToBeReturned.push(arr[randIndex]);
您会说对的,但这不是算法的作用。想象一下随机排序[1, 2, 3]
的数组:
循环的第一次迭代:i
为0,选择的随机索引为2。交换索引0和2:
[3, 2, 1]
第二次迭代:i
为1,选择的随机索引为2。交换索引1和2:
[3, 1, 2]
第三次迭代:i
是2,选择的随机索引是2。交换索引2和2:
[3, 1, 2]
使用此代码,每个索引至少一次与另一个索引 随机交换,以确保到最后,该数组被随机化而没有偏差(假设Math.random
是可信赖的)。
答案 1 :(得分:1)
Math.floor(Math.random()* n)是的,它可以eve求值到相同的索引,但是这里您使用数字来交换元素,所以没关系。
Math.random是否会自动撤回已使用的索引?
不,您不需要跟踪以前生成的值
您可以执行的操作是使用变量object
或Map
来跟踪先前添加的索引,如果该变量中尚未包含随机生成的索引,则将该变量添加到最终输出中,否则再次生成一个新索引,
但是在这种情况下不需要。