Как генерировать случайные числа с неповторяющимися цифрами в Java?
При использовании случайной утилиты в Java вы получаете несколько чисел, таких как: 1271, 34556, 177 и т. Д. Какой самый простой способ сделать это, чтобы цифры не повторялись?
6 ответов
Как насчет создания цикла, который проверяет, соответствует ли сгенерированное случайное число вашим требованиям.
final Random rnd = new Random(); int n; do < n = rnd.nextInt(1000); >while(containsRepeatingDigits(n));
containsRepeatingDigits может выглядеть так:
boolean containsRepeatingDigits(final int n) < final boolean digits[] = new boolean[10]; for(char c : String.valueOf(n).toCharArray()) < final int i = c-'0'; if(digits[i]) return true; digits[i] = true; >return false; >
Вы можете перемешать массив [1,2,3,4,5,6,7,8,9] и прочитать его как число.
Если вы не хотите фиксировать количество цифр или разрешать не ведущий ноль, это усложняется (если вы заботитесь о каком-то равном распределении).
Вы могли бы инициализировать List с цифрами 0-9 , Затем рандомизируйте этот список и опросите случайное количество элементов (от 1 до 9) из этого списка. Объедините цифры, и вы получите свой номер с неповторяющимися цифрами.
Вы можете проверить, имеет ли случайное число повторяющиеся цифры, и сгенерировать новое, если оно есть. Он написан на C#, но вы должны легко преобразовать его в Java.
private static Random rand = new Random(); public static int GenerateNumberNonRepeat() < int number; do < number = rand.Next(); >while (IsRepeating(number)); return number; > public static bool IsRepeating(int number) < string textual = number.ToString(); for (int i = 0; i < textual.Length; i++) < for (int j = i + 1; j < textual.Length; j++) < if (textual[i] == textual[j]) return true; >> return false; >
Другой способ генерации этих чисел состоит в том, чтобы генерировать произвольное число, и в случае, если оно содержит повторяющиеся цифры, либо генерируют новое, либо удаляют повторяющиеся цифры (например, увеличивая число, пока не останется больше повторяющихся чисел).
В отличие от предложенного подхода случайного выбора / выбора, это имеет то преимущество, что вы сохраняете (более или менее) распределение исходного rng.
Random, без повторений.
Можно ли стандартными средствами реализовать Random(100) допустим, который 2 раза одно число не выдаёт. Если у кого нибудь есть готовое решение, будет здорово. Нужно генерировать число и исключать его из диапазона. Надеюсь понятно объяснил. Чтобы Random(4) сгенерировав 3 исклюачал его из своего диапазона. Просто, если генерировать пока число будет удовлетворять условию, для маленьких чисел приемлемо а для больших затратно. Хочется, как то лаконичнее сделать.
Добавлено через 2 часа 3 минуты
Состряпал такую штуку, если кто попроще покажет, получит респектос )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
class RandomFour { private ArrayListInteger> input=new ArrayListInteger>(); Random rnd; int Count; public RandomFour(int in) { Count=in; rnd=new Random(in); } public int generate() } return -1; }
Добавлено через 11 минут
Есть баг, который пока не получается отловить. Метод почему то никогда не возвращает -1.
Зацикливается в методе already was, т.к после того , как массив input сожержит все значения Random метод alreadyWas всегда возвращает true
Java генерирует неповторяющиеся случайные числа
Я хочу создать набор случайных чисел без дубликатов в Java. Например, у меня есть массив для хранения 10 000 случайных чисел от 0 до 9999. Вот что я до сих пор:
import java.util.Random; public class Sort < public static void main(String[] args)< int[] nums = new int[10000]; Random randomGenerator = new Random(); for (int i = 0; i < nums.length; ++i)< nums[i] = randomGenerator.nextInt(10000); >> >
Вы хотите, чтобы все 10.000 чисел в массиве в случайном порядке, или вы хотите 10.000 случайных чисел? потому что вы не можете иметь 10.000 случайных чисел в диапазоне от 0 до 9.999 (тогда они больше не случайные)
Вы хотите, чтобы это не повторялось так, как повторяется «1 1 2»? Является ли «1 2 1» приемлемой последовательностью?
Хм, я не совсем уверен, что это домашнее задание, и мой учитель сказал, что нет повторений в задании, поэтому я думаю, что 121 будет приемлемым
@FernandoMartinez Почему вы хотите удалить этот вопрос? Вы должны выбрать лучший ответ и принять вместо этого. Дубликат не означает, что вы должны удалить вопрос.
Для домашней работы, пожалуйста, подумайте с вашим инструктором. Некоторые из представленных ниже концепций (ленивая оценка) могут выходить за рамки того, что вы должны изучать (неплохо, но обучение — это приведение учащихся к конечной точке по заданному пути — если они отклоняются от пути, они могут не добраться до конечной точки). Передача задания, которое использует эти понятия, которые вы не понимаете, хуже, чем сдача задания, которое не работает, потому что вы не изучили этот шаг и у вас могут возникнуть дополнительные трудности со следующим.
6 ответов
Integer[] arr = ; Collections.shuffle(Arrays.asList(arr));
public static void main(String[] args) < Integer[] arr = new Integer[1000]; for (int i = 0; i < arr.length; i++) < arr[i] = i; >Collections.shuffle(Arrays.asList(arr)); System.out.println(Arrays.toString(arr)); >
Shuffle отлично, но сначала вы должны создать массив, который содержит числа от 0 до 9999, а затем перемешать его. Кроме того, какова временная сложность перемешивания?
@Martinsos Я создал массив и перемешал его. Я не уверен, но я думаю, что временная сложность перемешивания должна быть O (n). Потому что, если просто сделать случайный обмен внутри массива.
Простой алгоритм, который дает вам случайные числа без дубликатов, можно найти в книге Programming Pearls. 127.
Внимание: результирующий массив содержит числа в порядке! Если вы хотите их в произвольном порядке, вы должны перетасовать массив, либо Fisher-Yates shuffle, либо используя список и вызов Collections.shuffle() .
Преимущество этого алгоритма состоит в том, что вам не нужно создавать массив со всеми возможными числами, а сложность выполнения по-прежнему линейна O(n) .
public static int[] sampleRandomNumbersWithoutRepetition(int start, int end, int count) < Random rng = new Random(); int[] result = new int[count]; int cur = 0; int remaining = end - start; for (int i = start; i < end && count >0; i++) < double probability = rng.nextDouble(); if (probability < ((double) count) / (double) remaining) < count--; result[cur++] = i; >remaining--; > return result; >
Примечание: (см. Раздел «Внимание») Collections.shuffle выполняет случайную последовательность Фишера-Йейтса, поэтому это не ситуация «или-или».
Вы правы, Collections.shuffle делает случайную запись Фишера-Йейтса, но вам нужен List чтобы использовать его. Arrays.asList требует, чтобы массив имел тип Integer а не int чтобы выполнить преобразование правильно, тогда вам не нужно выделять дополнительную память. Написание случайных чисел Фишера-Йейтса позволяет избежать преобразования, и дополнительная память не требуется.
просто пытаюсь понять, зачем нужна probability < ((double) count) / (double) remaining ? почему бы не заполнить массив от начала до конца и просто перемешать?
Если вам нужно сгенерировать числа с интервалами, это может быть так:
Integer[] arr = new Integer[((int) (Math.random() * (16 - 30) + 30))]; for (int i = 0; i < arr.length; i++) < arr[i] = i; >Collections.shuffle(Arrays.asList(arr)); System.out.println(Arrays.toString(arr));`
[1, 10, 2, 4, 9, 8, 7, 13, 18, 17, 5, 21, 12, 16, 23, 20, 6, 0, 22, 14, 24, 15, 3, 11, 19] Если вам нужно, чтобы ноль не покидал вас, вы могли бы поставить «if»
Ачинтья Джа имеет правильную идею здесь. Вместо того, чтобы думать о том, как удалить дубликаты, вы удаляете возможность создания дубликатов, в первую очередь.
Если вы хотите придерживаться массива int и хотите рандомизировать свой порядок (вручную, что довольно просто), выполните следующие действия.
- создать массив размера n.
- проведите цикл и инициализируйте каждое значение в индексе я до значения я (или я + 1, если вы хотите, чтобы числа от 1 до n, а не от 0 до n-1).
- Наконец, цикл через массив снова заменяет каждое значение для значения при случайном индексе.
Ваш код может быть изменен, чтобы выглядеть так:
import java.util.Random; public class Sort < // use a constant rather than having the "magic number" 10000 scattered about public static final int N = 10000; public static void main(String[] args) < //array to store N random integers (0 - N-1) int[] nums = new int[N]; // initialize each value at index i to the value i for (int i = 0; i < nums.length; ++i) < nums[i] = i; >Random randomGenerator = new Random(); int randomIndex; // the randomly selected index each time through the loop int randomValue; // the value at nums[randomIndex] each time through the loop // randomize order of values for(int i = 0; i < nums.length; ++i) < // select a random index randomIndex = randomGenerator.nextInt(nums.length); // swap values randomValue = nums[randomIndex]; nums[randomIndex] = nums[i]; nums[i] = randomValue; >> >
И если бы я был вами, я, скорее всего, сломал бы каждый из этих блоков на отдельные, более мелкие методы, а не на один большой основной метод.
Генерация уникальных случайных чисел в Java
Я пытаюсь получить случайные числа от 0 до 100. Но я хочу, чтобы они были уникальными, а не повторялись в последовательности. Например, если я получил 5 номеров, они должны быть 82,12,53,64,32, а не 82,12,53,12,32 Я использовал это, но он генерирует одинаковые числа в последовательности.
Random rand = new Random(); selected = rand.nextInt(100);
Вы можете создать случайную перестановку в диапазоне 1..100 (для этого есть известные алгоритмы), но остановитесь после определения первых n элементов.
17 ответов
- Добавьте каждое число в диапазон последовательно в структуре list.
- Shuffle it.
- Возьмите первый «n».
Вот простая реализация. Это напечатает 3 уникальных случайных числа из диапазона 1-10.
import java.util.ArrayList; import java.util.Collections; public class UniqueRandomNumbers < public static void main(String[] args) < ArrayListlist = new ArrayList(); for (int i=1; i Collections.shuffle(list); for (int i=0; i > >
Первая часть исправления с исходным подходом, как отметил Марк Байерс в ответе, который теперь удален, заключается в использовании только одного экземпляра Random .
Это то, что приводит к тому, что числа идентичны. Экземпляр Random засевается текущим временем в миллисекундах. Для определенного начального значения случайный экземпляр вернет ту же самую последовательность псевдослучайных чисел.
С помощью Java 8+ вы можете использовать ints метод Random , чтобы получить IntStream случайных значений, затем distinct и limit , чтобы уменьшить поток до нескольких уникальных случайных значений.
ThreadLocalRandom.current().ints(0, 100).distinct().limit(5).forEach(System.out::println);
Random также имеет методы, которые создают LongStream и DoubleStream , если вам это нужно.
Если вы хотите, чтобы все (или большая сумма) чисел в диапазоне в произвольном порядке, было бы более эффективно добавлять все числа в список, перетасовывать его и принимать первое n, потому что приведенный выше пример в настоящее время реализуется путем генерации случайных чисел в запрошенном диапазоне и передачи их через набор (аналогично Rob Kielty answer), который может потребовать генерации гораздо большего, чем сумма, переданная потому что вероятность генерации нового уникального числа уменьшается с каждым найденным. Вот пример другого способа:
List range = IntStream.range(0, 100).boxed() .collect(Collectors.toCollection(ArrayList::new)); Collections.shuffle(range); range.subList(0, 99).forEach(System.out::println);
Я нуждался в этом для некоторого кода, который я Arrays#setAll() , и Arrays#setAll() немного быстрее, чем поток. Итак: `Integer [] indices = new Integer [n]; Arrays.setAll (индексы, я -> я); Collections.shuffle (Arrays.asList (индексы)); return Arrays.stream (indices) .mapToInt (Integer :: intValue) .toArray (); `
- Создайте массив из 100 чисел, а затем производите их порядок.
- Создайте генератор псевдослучайных чисел, который имеет диапазон 100.
- Создайте булевский массив из 100 элементов, затем установите элемент true, когда вы выберете этот номер. Когда вы выбираете следующую проверку числа против массива и повторите попытку, если элемент массива установлен. (Вы можете создать простой и понятный логический массив с массивом long , где вы смещаете и маскируете доступ к отдельным битам.)