【问题标题】:How do I generate random numbers from an array without repetition?如何从数组中生成随机数而不重复?
【发布时间】:2016-07-28 15:59:16
【问题描述】:

我知道以前有人问过类似的问题,但请耐心等待。

我有一个数组:

int [] arr = {1,2,3,4,5,6,7,8,9};

我希望数字随机生成 10 次。像这样的:

4,6,8,2,4,9,3,8,7

虽然有些数字是重复的,但没有一个数字会连续生成超过一次。所以不是这样的:

7,3,1,8,8,2,4,9,5,6

如您所见,数字 8 在生成后立即重复。这不是我们想要的效果。

所以基本上,我可以接受重复的数字,只要它连续出现不超过一次。

【问题讨论】:

  • 给我们看一些代码。您尝试了什么,遇到了什么问题?
  • 这个问题被称为“无放回随机抽样”。研究得很透彻。
  • @AShelly:除了这不是这里的问题。你说的问题是重复想要never重复一个数字。 OP 的问题是避免连续两次重复给定数字,但您可以合法地产生8, 4, 8。如果这是重复的,我不会感到惊讶,但它不是您在作为重复关闭时链接的那个。
  • 我明白了,我很抱歉。
  • @kiraa 的答案是具有确定性时间的正确解决方案。

标签: arrays sorting random


【解决方案1】:
  • 生成一个随机数。
  • 将其与您生成的最后一个数字进行比较
  • 如果相同;丢弃它
  • 如果不一样,添加到数组中
  • 返回第 1 步,直到你有足够的数字

【讨论】:

    【解决方案2】:
    1. 在数组中生成一个随机索引。

    2. 重复直到它与上次使用的索引不同。

    3. 将该索引对应的值拉出数组。

    4. 从头开始重复,直到获得所需数量的数字。

    【讨论】:

      【解决方案3】:

      虽然发布的答案还不错并且效果很好,但有人可能会对解决方案不满意,因为如果您生成足够长的序列,它可能会挂起(很难难以置信不太可能)相同的数字。

      处理这个“问题”,同时保留数字分布的算法是:

      • 从原始数组中选择一个随机数,我们称之为n,然后输出。
      • 制作除 n 之外的所有元素的数组
      • 从较短的数组生成随机索引。用 n 交换索引上的元素。输出 n
      • 重复上一步,直到输出足够的数字。

      【讨论】:

      • 您可以通过将项目n 与最后一个元素交换来跳过步骤2 中的复制,然后从[0..size-1) 范围内选择一个元素
      【解决方案4】:
          int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
          int[] result = new int[10];
          int previousChoice = -1;
      
          int i = 0;
          while (i < 10) {
              int randomIndex = (int) (Math.random() * arr.length);
              if (arr[randomIndex] != previousChoice) {
                  result[i] = arr[randomIndex];
                  i++;
              }
          }
      

      【讨论】:

        【解决方案5】:

        到目前为止给出的解决方案都涉及每一代的非恒定工作;如果您反复生成索引并测试重复,您可以想象在最终获得新索引之前多次生成相同的索引。 (Kiraa's answer 是一个例外,但它涉及高昂的常量开销来制作部分数组的副本)

        这里的最佳解决方案(假设您想要唯一索引,而不是唯一值,和/或源数组具有唯一值)是循环索引,以便您始终在(低)恒定时间内生成新索引。

        基本上,你会有一个这样的 with 循环(使用 Python 作为语言主要是为了简洁):

        # randrange(x, y) generates an int in range x to y-1 inclusive
        from random import randrange
        
        arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
        result = []
        selectidx = 0
        randstart = 0
        
        for _ in range(10):  # Runs loop body 10 times
            # Generate offset from last selected index (randstart is initially 0
            # allowing any index to be selected; on subsequent loops, it's 1, preventing
            # repeated selection of last index
            offset = randrange(randstart, len(arr))
            randstart = 1
        
            # Add offset to last selected index and wrap so we cycle around the array
            selectidx = (selectidx + offset) % len(arr)
        
            # Append element at newly selected index
            result.append(arr[selectidx])
        

        这样,保证每个生成步骤只需要一个新的随机数,唯一不变的额外工作是单次加法和余数运算。

        【讨论】:

          猜你喜欢
          • 2018-07-03
          • 1970-01-01
          • 2012-08-30
          • 2013-07-02
          • 1970-01-01
          • 2015-07-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多