创建没有重复的随机数 [英] 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).
这不能很好地工作如果你想要(比方说)10个随机元素在1..10,000范围内 - 你最终会不必要地做很多工作。此时,最好保留到目前为止生成的一组值,并且只是在循环中生成数字,直到下一个尚未出现:
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屋!