创建没有重复的随机数 [英] Creating random numbers with no duplicates

查看:25
本文介绍了创建没有重复的随机数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这种情况下,MAX 只有 5,所以我可以一一检查重复项,但我怎样才能以更简单的方式做到这一点?例如,如果 MAX 的值为 20 会怎样?谢谢.

In this case, the MAX is only 5, so I could check the duplicates one by one, but how could I do this in a simpler way? For example, what if the MAX has a value of 20? Thanks.

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..20 或其他),然后使用 Collections.shuffle.然后只要你想要多少元素就可以了.如果您的范围等于您最终需要的元素数量(例如,用于洗牌),那就太好了.

The simplest way would be to create a list of the possible numbers (1..20 or whatever) and then shuffle them with Collections.shuffle. Then just take however many elements you want. This is great if your range is equal to the number of elements you need in the end (e.g. for shuffling a deck of cards).

如果您想要(例如)1..10,000 范围内的 10 个随机元素,那效果不佳 - 您最终会做很多不必要的工作.在这一点上,最好保留一组迄今为止生成的值,并继续在循环中生成数字,直到下一个尚未出现:

That doesn't work so well if you want (say) 10 random elements in the range 1..10,000 - you'd end up doing a lot of work unnecessarily. At that point, it's probably better to keep a set of values you've generated so far, and just keep generating numbers in a loop until the next one isn't already present:

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 因为它维护插入顺序,我们在这里关心.

Be careful with the set choice though - I've very deliberately used LinkedHashSet as it maintains insertion order, which we care about here.

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

Yet another option is to always make progress, by reducing the range each time and compensating for existing values. So for example, suppose you wanted 3 values in the range 0..9. On the first iteration you'd generate any number in the range 0..9 - let's say you generate a 4.

在第二次迭代中,您将生成一个范围为 0..8 的数字.如果生成的数字小于 4,您将保持原样……否则您将添加一个.这样得到的结果范围是 0..9 而没有 4.假设我们这样得到 7.

On the second iteration you'd then generate a number in the range 0..8. If the generated number is less than 4, you'd keep it as is... otherwise you add one to it. That gets you a result range of 0..9 without 4. Suppose we get 7 that way.

在第三次迭代中,您将生成一个范围为 0..7 的数字.如果生成的数字小于 4,则保持原样.如果是 4 或 5,则添加一个.如果是 6 或 7,则添加两个.这样结果范围是 0..9,没有 4 或 6.

On the third iteration you'd generate a number in the range 0..7. If the generated number is less than 4, you'd keep it as is. If it's 4 or 5, you'd add one. If it's 6 or 7, you'd add two. That way the result range is 0..9 without 4 or 6.

这篇关于创建没有重复的随机数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆