一尘不染

Java创建无重复的随机数

java

在这种情况下,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;
        }

}

阅读 395

收藏
2020-02-25

共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,则要加1。如果是6或7,则要加两个。这样,结果范围是0..9,没有4或6。

2020-02-25