【问题标题】:Is it possible to iterate over an array in random order?是否可以以随机顺序遍历数组?
【发布时间】:2021-04-09 20:43:38
【问题描述】:

所以,假设我有一个数组:

int arr[5];

除了从 0 到 4 遍历数组之外,是否可以按随机顺序执行此操作,并且迭代器不会两次遍历同一位置?

【问题讨论】:

  • 当然,您只需要实现一个自定义迭代器即可。 C++ 可以做任何事情。您是否尝试过实现自己的自定义迭代器?
  • 根据数组的大小,你最好只使用suffle,然后像往常一样迭代
  • 或者生成第二个整数数组,包含值04。打乱第二个数组,并将其元素用作第一个数组的索引。
  • @SamVarshavchik 不是真的,我不知道那是一回事。我查一下
  • @wintersun 它必须有多随机,例如,您是否需要保证所有可能的排列都会发生?如果没有,一种便宜的方法是选择一个介于 0 和 4 之间的随机起始索引 n,以及一个介于 1 和 4 之间的随机步长 k,然后迭代索引 n = (n + k) % 5。与普通索引增量相比,这将为您提供 20 种不同的排列,同时不需要额外的空间和可忽略的额外时间。

标签: c++ arrays loops


【解决方案1】:

以下所有内容都假设您想在 O(1) 空间中实现迭代 - 不使用例如索引的辅助数组,您可以对其进行洗牌。如果你能负担得起 O(n) 的空间,解决方案相对容易,所以我假设你只能负担 O(1)。

要以随机方式迭代数组,您可以创建一个随机数生成器,并将其输出用作数组的索引。您不能以这种方式使用标准 RNG,因为它们可以过早两次输出相同的索引。但是,RNG 的理论相当广泛,至少有两种类型的 RNG 可以保证它们的周期。

使用这些理论思想:

  1. 选择一个数字 N ≤ n(其中 n 是数组的大小),但不要比 n 大太多,这样就可以构造一个周期为 N 的 RNG
  2. 调用您的 RNG N 次,因此它会生成从 0 到 N-1 的数字排列
  3. 对于每个数字,如果它小于数组的大小,则输出具有该索引的数组元素

制作具有给定周期的 RNG 的技术可能太烦人而无法在代码中实现。因此,如果您事先知道数组的大小,您可以选择 N = n,并手动创建您的 RNG(分解 n 或 n+1 将是第一步)。如果您不知道数组的大小,请为 N 选择一些易于使用的数字,例如 2 的某个合适的幂。

【讨论】:

    【解决方案2】:

    如 cmets 中所述,您可以通过多种方式执行此操作。最明显的方法是只使用shuffle 范围,然后对其进行迭代:

    std::shuffle(arr, arr + 5);
    
    for (int a : arr) 
      // a is a new random element from arr in each iteration
    

    这当然会修改范围,这可能不是你想要的。


    对于不修改范围的选项:您可以生成一个索引范围,将这些索引打乱并使用这些索引来索引该范围:

    int ind[5];
    std::iota(ind, ind + 5, 0);
    std::shuffle(ind, ind + 5);
    
    for (int i : ind)
      // arr[i] is a new random element from arr in each iteration
    

    您还可以实现一个自定义迭代器,该迭代器以随机顺序迭代一个范围而不重复,尽管这对于您想要实现的功能来说可能是多余的。尝试一下,了解它的工作原理仍然是一件好事。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-13
      • 1970-01-01
      • 2012-11-19
      相关资源
      最近更新 更多