【问题标题】:Iterate over a random permutation of numbers in the range 0..n with large n迭代 0..n 范围内数字的随机排列,其中 n 较大
【发布时间】:2021-12-02 21:25:58
【问题描述】:
我需要遍历0..n 范围内整数的随机排列。
我的第一个想法是创建一个连续整数数组并对其进行洗牌。它适用于较小的n,但会变慢并且使用较大的ns (n > 1000000) 的内存过多。 (请参阅:https://jsfiddle.net/cveqm4nj/ 在我的机器上运行需要 >100 毫秒)
如何在不分配大小为 n 的数组的情况下创建一个返回 0..n 范围内的非重复整数的迭代器?
【问题讨论】:
标签:
algorithm
random
numbers
permutation
【解决方案1】:
在done right 的情况下,洗牌真的很容易、非常快并且根本不使用额外的内存。 (不过,您仍然需要输入数组的内存。)
function shuffle_inplace(array) {
let i = array.length;
while (i > 0) {
let j = Math.floor(Math.random() * i);
--i;
[ array[i], array[j] ] = [ array[j], array[i] ];
}
}
洗牌:
- 这使用 O(N) 时间。
- 这使用 O(1) 内存。
包括构建数组:
- 这使用 O(N) 时间。
- 这使用 O(N) 内存。
这可以变成一个迭代器,这样你就可以在每次调用它时返回一个值。
function make_destructive_shuffle_iter(array) {
let i = array.length;
return function() {
if (i == 0)
return null;
let j = Math.floor(Math.random() * i);
--i;
[ array[i], array[j] ] = [ array[j], array[i] ];
return array.pop();
};
}
但这仍然需要 O(N) 内存。需要 O(N) 内存来跟踪您已经使用/返回的输入。但是该内存不需要是RAM。您可以改用磁盘。