Вопрос-ответ

Creating random numbers with no duplicates

Создание случайных чисел без дубликатов

В этом случае МАКСИМАЛЬНОЕ значение равно только 5, поэтому я мог бы проверять дубликаты одно за другим, но как я мог бы сделать это более простым способом? Например, что, если МАКСИМАЛЬНОЕ значение равно 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. Затем просто возьмите столько элементов, сколько захотите. Это здорово, если ваш диапазон равен количеству элементов, которые вам нужны в конечном итоге (например, для перетасовки колоды карт).

Это работает не так хорошо, если вам нужно (скажем) 10 случайных элементов в диапазоне 1 .. 10 000 - в конечном итоге вы выполняете много ненужной работы. На этом этапе, вероятно, лучше сохранить набор значений, которые вы сгенерировали до сих пор, и просто продолжать генерировать числа в цикле, пока не появится следующее:

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);
}

Однако будьте осторожны с выбором set - я использовал его очень сознательно, LinkedHashSet поскольку он поддерживает порядок вставки, о котором мы здесь заботимся.

Еще один вариант - всегда добиваться прогресса, каждый раз уменьшая диапазон и компенсируя существующие значения. Итак, например, предположим, что вам нужны 3 значения в диапазоне 0 .. 9. На первой итерации вы сгенерируете любое число в диапазоне 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, вам, вероятно, следует использовать мой метод, заполнив список, содержащий все пространство выборки, а затем удаляя из него числа по мере их выбора.

Ответ 3
//random numbers are 0,1,2,3 
ArrayList<Integer> numbers = new ArrayList<Integer>();
Random randomGenerator = new Random();
while (numbers.size() < 4) {

int random = randomGenerator .nextInt(4);
if (!numbers.contains(random)) {
numbers.add(random);
}
}
Ответ 4

Это было бы намного проще в java-8:

Stream.generate(new Random()::ints)
.flatMap(IntStream::boxed)
.distinct()
.limit(16) // whatever limit you might need
.toArray(Integer[]::new);
java