【问题标题】: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。您可以改用磁盘。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-20
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多