2012-05-21 2 views
0

Можно создать дубликат:
Generating Unique Random Numbers in JavaСформировать уникальное случайное число в диапазоне от 0 до 1000

Как я могу генерировать случайное число в диапазоне от 0 до 1000 и сохранить при переходе уникального случайного числа, которое получило генерируемую между 0 и 1000 для конкретного метода. Поэтому для этого я сгенерировал число от 0 до 1000 и вставил уникальное случайное число между 0 и 1000 в List, чтобы мы могли сравнить, является ли случайное число, которое мы генерируем, уже присутствует в списке или нет. Если он присутствует, то сгенерируйте его снова. Но почему-то я считаю, что нижеприведенный код не сработает.

public class Testing4 { 
    private static List<Integer> randomNumber; 
    private static Random r = new Random(); 
    private static int rand; 
    private static int endRange = 1000; 

    public static void main(String args[]) throws IOException { 

     randomNumber = new ArrayList<Integer>(); 

     for (int i = 1; i<= endRange; i++) { 
      rand = r.nextInt(endRange); 

      if(randomNumber.contains(rand)) { 
       rand = r.nextInt(endRange); 
      } else { 
       randomNumber.add(rand); 
      } 

     // Pass the unique random number between 0 and 1000 to this method  
       randomNumberMethod(rand); 

     } 
    } 
} 
+7

У меня нет кода для него с верхней части моей головы, но в основном: создать список целых чисел от 0 до 1000 и перетасовать ее, а затем вернуться каждый из этих значений по одному. Это гораздо меньше, чем попытка отслеживать то, что вы уже видели. –

+0

Вы даже серьезно? Мне потребовалось 10 минут, чтобы написать отличный ответ. И он заперся. Я так расстроен. –

+0

@ Andrius, Можете ли вы скопировать сюда, чтобы я мог видеть, что является самым эффективным способом сделать это? Или я могу указать свой адрес электронной почты. – AKIWEB

ответ

0

Ваш код не сработает, если сгенерированы 2 номера, которые уже существуют в вашем ArrayList. Он будет использовать второе число, будь то дубликат или нет. Оператор if должен быть циклом while (чтобы продолжать попытки, пока он не генерирует уникальный).

public class Testing4 { 
    private static HashSet<Integer> randomNumber; 
    private static Random r = new Random(); 
    private static int rand; 
    private static int endRange = 1000; 

    public static void main(String args[]) throws IOException { 

     randomNumber = new HashSet<Integer>(); 

     for (int i = 1; i<= endRange; i++) {  
      do 
      { 
       rand = r.nextInt(endRange); 
      } 
      while(randomNumber.contains(rand)); 

      randomNumber.add(rand); 

      // Pass the unique random number between 0 and 1000 to this method  
      randomNumberMethod(rand); 

     } 
    } 
} 

редактировать: согласно комментариям, вы должны использовать делать/в то время как и структура хэширования данных, а не ArrayList, чтобы ускорить повторяющиеся поиск. Окончательные изменения указаны в коде выше.

+0

Цикл «do while» здесь более уместен. – Nican

+0

Это правда (для аккуратности), я отредактирую свой ответ. – Dima

+0

Основная проблема с этим подходом заключается в том, что он резко сократится, поскольку 'randomNumber.length()' подходит к endRange'. Когда 'randomNumber' пуст, для добавления потребуется ровно одна итерация цикла while. Когда он будет почти заполнен, перед выполнением этой команды потребуются приблизительно итерации endRange. –

2

Чтобы создать уникальный список чисел от 0 до 1000, выполните следующие действия:

  • создать список, содержащий все числа от 0 до 1000
  • перетасовать список с помощью Collections.shuffle()
  • возьмите первое, но много чисел, которое вам нужно из списка.

Есть случаи, когда более сложный алгоритм называется, но если диапазон возможных чисел и количество элементов, которые необходимо выбрать оба в порядке 1000 вы действительно можете также просто взять первый n номера из случайного перетасованного списка всех возможностей.

Если вы хотите сделать что-то, как вы предлагаете, то:

  • использовать цикл в то время как другой плакат предложил
  • использовать комплект, не список, чтобы сохранить уже выбранные значения ,

Однако это становится неэффективным, поскольку количество элементов для выбора имеет тенденцию к величине по отношению к количеству возможных элементов (так, например, если вы выбираете 10 номеров из возможных 1000, тогда все будет в порядке; вы выберете 900 из возможных 1000, это станет неэффективным, так как все больше и больше номеров нужно отбрасывать каждый раз, прежде чем находить тот, который ранее не был выбран).

+0

Можете ли вы показать мне пример из моего кода, как он будет работать? – AKIWEB

3

Вы по существу генерируете список чисел от 0 до 1000 в случайном порядке. Вы могли бы добиться этого более эффективно следующим образом:

public class Testing4 { 
    private static List<Integer> randomNumber; 
    private static int endRange = 1000; 

    public static void main(String args[]) throws IOException { 

     randomNumber = new ArrayList<Integer>(endRange); 

     for (int i = 0; i<= endRange; i++) {     
      randomNumber.add(i); 
     } 

     Collections.shuffle(randomNumber); 

     for (int i = 0; i<= endRange; i++) {     
      // Pass the unique random number between 0 and 1000 to this method  
      randomNumberMethod(randomNumber.get(i)); 
     } 
    } 
} 

Подумайте о том, что будет происходить по времени, вы получите до 999 - у вас будет 1 в 999 шанс «угадывание» на оставшееся количество каждый раз, вокруг цикла.

+0

В какой-то момент это дает мне IndexOutOfBoundException. – AKIWEB

+0

Ответа на этот вопрос. Ваш исходный код зациклился от 1 до 1000, но я вижу из вашего текста, что вы действительно хотите 0-1000. Мой код некорректно начинался с 1 во втором цикле, вызывая IndexOutOfBoundException, но если оба они были изменены, чтобы начать с 0, вы получите поведение, которое вы ищете. –

+0

Спасибо за обновление Malcolm, поэтому, если мне нужно случайное число от 0 до 1001, я могу изменить в цикле for как «i AKIWEB

1

Из проверки кода я ничего не вижу в этом методе, который остановит его от WORKING, это просто очень неэффективно.

С одной стороны, проверяя, является ли номер тем, что вы видели, все больше и больше времени будет больше, чем больше вы генерируете, так как каждый раз, когда вы это делаете, вам придется сравнивать его с каждым числом в пока вы не найдете тот, который соответствует, или вы пробовали каждый номер в списке. Лучший способ сделать это - использовать HashSet вместо списка, который должен сделать каждый тест на членство равным количеством времени, независимо от того, сколько вещей вы положили в него.

Вторая, и более значительная оптимизация может быть выполнена путем уведомления о том, что вы можете задавать неправильный вопрос. Вы пытаетесь генерировать уникальные случайные числа или пытаетесь генерировать каждое число между 1 и endRange в случайном порядке? Если вам захочется, чтобы каждое число (или даже нетривиальная часть) было намного быстрее, просто введите каждое число от 1 до 1000 в список, а затем перетасуйте их, используя Collections.shuffle. Так что ваш код поколения будет:

java.util.List<Integer> nums = new java.util.ArrayList<Integer>(1001); 
for (int i = 0; i <= 1000; i++) 
{ 
    nums.add(new Integer(i)); 
} 
java.util.Collections.shuffle(nums); 
Смежные вопросы