有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

在Java中生成范围内的非重复随机数

我想生成1到4之间的随机数,包括
这是我的代码:

int num = r.nextInt(4) + 1;  //r is instance of Random.

然而,我在循环中运行上述代码,不希望重复随机数。 现在发生的事情我经常会得到:
1,1,1,2,3,1,4,2,2,1,4,2,4,4,2,1,4,3,3,1,4,2,4,1作为我的输出

在这里,虽然数字在范围(1-4)内是随机的,但在前3次迭代中经常像数字“1”一样重复

我要寻找的是一种在循环中获得非重复随机数的方法。 我知道的一个简单方法是在当前迭代之前保留最后一个随机数并进行比较,但我相信一定有更好的解决方案
提前谢谢


共 (4) 个答案

  1. # 1 楼答案

    下面是一个算法:

    initialize an array A[4] with the numbers 1-4
    set a counter Acnt, the effective size of A. Initialize to 4
    for i in 1 to length(output sequence)
       choose a random integer X from 0 to Acnt -1
       save A[X] to your output sequence
       swap(A[X],A[Acnt - 1])
       Acnt--
       if(Acnt == 0) Acnt = lengh(A)
    

    想象A是一袋数字为1-4的球。循环的每一次迭代,你都会移除一个球。你只需将球隐藏在数组的末尾,而不是从数组中实际删除球(这很昂贵)。当您减少包中的球数(Acnt)时,您选择的下一个球来自非隐藏球

    当你没有更多的球可供选择时,你可以通过将包中的球数重置为满数来取消隐藏球

    这基本上是标准的洗牌算法

    编辑:重新阅读这个问题,我知道现在他只允许在1个数字之后重复,而不是整个序列,在这种情况下,您只需要将if(Acnt==0)更改为if(Acnt==length(A)-1)

  2. # 2 楼答案

    没有“更好”的答案。 你会得到一个随机数。检查这行:

    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
    

    这可能是完全随机的。 所以我建议你描述一个更好的要求。 您是否总是希望下一个号码与上一个号码不同?你想在特殊范围内最多复制一次吗?假设在6个连续的数字中,每个数字都允许出现两次

    如果你提出这样的要求,我们也许能帮助你。否则我们只能说:你看到的真的是随机的:)

  3. # 3 楼答案

    因为你有比你必须选择的更多的数字,你必须重复一些数字。你所能做的就是尽量减少立即重复的次数

    一种方法是使用集合。洗牌,让你有一个随机顺序的数字,没有重复,并这样做每一次。可以防止重复最后的N值

    要停止连续重复的数字,可以减小范围并使用模数

    int n = 0, max = 4;
    Random rand = new Random();
    
    for(int i = 0; i < numbers; i++) {
       n = (n + rand.nextInt(max-1)) % max;
       int numToUse = n + 1;
       // use this number.
    }
    

    这是可行的,因为实际上只有max-1个可能的值,因为您排除了最后使用的值

  4. # 4 楼答案

    使用random.nextInt(range-1),然后使用排除前一个数字的函数将该数字映射到输出数字:

    public class Test {
      private final Random random = new Random();
      private final int range;
      private int previous;
    
      Test(int range) { this.range = range; }
    
      int nextRnd() {
        if (previous == 0) return previous = random.nextInt(range) + 1;
        final int rnd = random.nextInt(range-1) + 1;
        return previous = (rnd < previous? rnd : rnd + 1);
      }
    
    
      public static void main(String[] args) {
        final Test t = new Test(4);
        for (int i = 0; i < 100; i++) System.out.println(t.nextRnd());
      }
    }