创建没有重复的随机数 [英] Creating random numbers with no duplicates
问题描述
在这种情况下,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屋!