创建没有重复项的随机数

2022-08-31 10:33:15

在这种情况下,MAX只有5,所以我可以逐个检查重复项,但是我怎么能用更简单的方式做到这一点呢?例如,如果 MAX 的值为 20,该怎么办?谢谢。

int MAX = 5;

for (i = 1 , i <= MAX; i++)
{
        drawNum[1] = (int)(Math.random()*MAX)+1;

        while (drawNum[2] == drawNum[1])
        {
             drawNum[2] = (int)(Math.random()*MAX)+1;
        }
        while ((drawNum[3] == drawNum[1]) || (drawNum[3] == drawNum[2]) )
        {
             drawNum[3] = (int)(Math.random()*MAX)+1;
        }
        while ((drawNum[4] == drawNum[1]) || (drawNum[4] == drawNum[2]) || (drawNum[4] == drawNum[3]) )
        {
             drawNum[4] = (int)(Math.random()*MAX)+1;
        }
        while ((drawNum[5] == drawNum[1]) ||
               (drawNum[5] == drawNum[2]) ||
               (drawNum[5] == drawNum[3]) ||
               (drawNum[5] == drawNum[4]) )
        {
             drawNum[5] = (int)(Math.random()*MAX)+1;
        }

}

答案 1

最简单的方法是创建一个可能数字(1..20或其他)的列表,然后用.然后,只需采取您想要的元素。如果你的范围等于你最终需要的元素数量(例如,洗牌一副牌),那就太好了。Collections.shuffle

如果你想要(比如说)1..10,000范围内的10个随机元素,那就不太管用了 - 你最终会做很多不必要的工作。此时,最好保留到目前为止生成的一组值,并继续在循环中生成数字,直到下一个值尚不存在:

if (max < numbersNeeded)
{
    throw new IllegalArgumentException("Can't ask for more numbers than are available");
}
Random rng = new Random(); // Ideally just create one instance globally
// Note: use LinkedHashSet to maintain insertion order
Set<Integer> generated = new LinkedHashSet<Integer>();
while (generated.size() < numbersNeeded)
{
    Integer next = rng.nextInt(max) + 1;
    // As we're adding to a set, this will automatically do a containment check
    generated.add(next);
}

不过要小心设置选择 - 我非常刻意地使用它,因为它维护了插入顺序,我们在这里关心。LinkedHashSet

另一种选择是始终取得进展,每次都缩小范围并补偿现有值。例如,假设您想要 0..9 范围内的 3 个值。在第一次迭代中,您将生成0..9范围内的任何数字 - 假设您生成一个4。

在第二次迭代中,您将生成一个介于 0..8 之间的数字。如果生成的数字小于 4,则应保持原样...否则,您可以向其添加一个。这让你的结果范围是0..9,没有4。假设我们以这种方式得到7。

在第三次迭代中,您将生成一个介于 0 到 7 之间的数字。如果生成的数字小于 4,则应保持原样。如果是 4 或 5,则添加一个。如果是 6 或 7,则添加两个。这样,结果范围为 0..9,而不带 4 或 6。


答案 2

这是我怎么做到的

import java.util.ArrayList;
import java.util.Random;

public class Test {
    public static void main(String[] args) {
        int size = 20;

        ArrayList<Integer> list = new ArrayList<Integer>(size);
        for(int i = 1; i <= size; i++) {
            list.add(i);
        }

        Random rand = new Random();
        while(list.size() > 0) {
            int index = rand.nextInt(list.size());
            System.out.println("Selected: "+list.remove(index));
        }
    }
}

正如受人尊敬的斯基特先生所指出的:
如果n是你想要选择的随机选择的数字的数量,N是可供选择的数字的总样本空间:

  1. 如果 n << N,则只需存储已选取的数字并检查列表以查看所选数字是否在其中。
  2. 如果 n ~= N,则可能应该使用 my 方法,方法是填充包含整个样本空间的列表,然后在选择数字时从中删除数字。

推荐