Java-массивы и случайные числа

1

Я пытаюсь создать массив случайных чисел. Каждая запись массива будет иметь число от 0 до 31. Я пытаюсь получить код для генерации случайного числа, а затем проверить, существует ли это число в массиве. Если да, то он генерирует новое случайное число и снова проверяет с начала.

Я подумал, что я понял это с помощью кода ниже:

 public class HelloWorld{

     public static void main(String []args){
        int[] randArray = new int[10];
        boolean firstNumber = true;
        int randNum = 0;

        for (int j=0; j < randArray.length; j++) {

            if(firstNumber) {
                randNum = (int)(Math.random() * 31 + 1);
                randArray[j] = randNum;
                firstNumber = false;
            } else {
                for (int k=0; k < randArray.length;) {
                    randNum = (int)(Math.random() * 31 + 1);
                    if(randArray[k] == randNum) {
                        k=0;
                    } else { 
                       k++;   
                    }
                }
                randArray[j] = randNum;
                System.out.println(j);
            }
        }

        System.out.println("-------");

        for(int i=0; i < randArray.length; i++) {

            System.out.println(randArray[i]);

        }
    }
}

Но это то, что он печатает:

1 2 3 4 5 6 7 8 9 ------- 25 17 19 20 24 4 26 30 6 24

Как вы можете видеть, 24 повторяется дважды. Если я снова запустил код, вы можете увидеть повторяющиеся числа, которые повторяются.

По логике я не могу понять, почему это делается. Это может быть что-то простое, но я просто не вижу этого.

Я новичок в программировании, и это то, о чем я думал, что смогу проверить свои знания.

Теги:
arrays

7 ответов

2
Лучший ответ

Вы можете попробовать этот код:

public static void main(String[] args) {
    Set<Integer> set = new HashSet<>();
    while (set.size() < 10) set.add((int)(Math.random() * 31) + 1);
    Integer[] randArray = set.toArray(new Integer[0]);
    for (int i = 0; i < randArray.length; i++) {
        System.out.print(randArray[i] + " ");
    }
    System.out.println();
}

ПРИМЕР ВЫХОДА:

2 3 4 21 6 7 10 29 12 14
  • 0
    как проверить, чтобы увидеть, что случайное число еще не существует в массиве?
  • 2
    Сам набор - это коллекция, которая не может содержать повторяющиеся элементы. tutorialspoint.com/java/java_set_interface.htm
Показать ещё 4 комментария
3

Ваш подход к генерации уникальных случайных чисел неверен, потому что, когда вы добираетесь до последнего числа n в своем массиве, у вас есть только 1/n шанс создать тот конкретный номер, который вам нужен. И поскольку вы работаете со случайными числами, может случиться так, что вы можете долго ждать, прежде чем успешно сгенерировать весь массив. Кроме того, время генерации массива дико непредсказуемо.

Гораздо лучший способ сделать это - создать массив с возрастающей последовательностью и перетасовать этот массив. Таким образом, вы гарантированно сгенерируете массив в O (n) и перетасовываете массив в O (n).

int arraySize=32;
int[] myArray= new int(arraySize);
for(int i=0;i<arraySize;i++) {
    myArray[i]=i;
}
for(int i=0;i<arraySize;i++) {
    int randNum = (int)(Math.random() * (arraySize-1));
    int tmp=myArray[randNum];
    myArray[randNum]=myArray[i];
    myArray[i]=tmp;
}
  • 0
    интересно - не могли бы вы уточнить? Я думал о настройке массива без фиксированной длины, но, насколько я понимаю, вам нужно выделить размер для массива при первом его создании
  • 0
    добавленный код показывает, как это можно сделать. Моя Java немного ржавая, но, надеюсь, вы понимаете решение.
2

Другое решение. Отметьте числа, которые были сгенерированы.

public static void main(String[] args) {
    int[] randArray = new int[10];
    int randNum = 0;
    boolean[] isPresented = new boolean[32];

    for (int i = 0; i < randArray.length; ) {
        randNum = (int)(Math.random() * 31 + 1);
        if(!isPresented[randNum]){
            randArray[i] = randNum ;
            isPresented[randNum] = true;
            i++;
        }
    }
    System.out.println(Arrays.toString(randArray));
}
2

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

Здесь вы должны проверить весь массив на одно и то же случайное число, и если вы найдете совпадение, установите k в 0 и восстановите случайное число, чтобы повторить попытку.

  • 0
    Это правильный ответ относительно того, почему вы получаете дубликаты. Вы создаете новое случайное число во внутреннем k=0; k < randArray.length loop. Вы проверяете новое случайное число с одним индексом в randArray вместо того же случайного числа с каждым индексом. Если вы создаете случайное число в j=0; ... цикл вместо, если должен работать. Кроме того, вы можете избавиться от содержимого firstNumber, просто инициализируя randArray [0] новым случайным числом и выполняя цикл с j=1; j < randArray.length .
2

Я бы использовал Shuffle Fisher-Yates, чтобы сделать это. Это самый быстрый способ, который я знаю, за счет небольшого избыточного потребления памяти. Но он не страдает от лишних попыток.

/*pseudocode; populate 'arr' to taste. I'd be tempted to write it long-hand*/
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ..., 31}; 
/*Implement Fisher-Yates shuffle in its own scope block*/
{
    Random random = new Random();
    for (int i = arr.length - 1; i > 0; i--){
        int r = random.nextInt(i + 1);
        /*exhange r and i*/
        int t = arr[r];
        arr[r] = arr[i];
        arr[i] = r;
    }
}
/*ToDo - either rescale 'arr' or just use the first 10 elements*/
1

Во втором цикле for вы генерируете случайное число для каждой итерации цикла. Измените петлю, как показано ниже.

else {
            // generate a random number before the loop begins
            randNum = (int)(Math.random() * 31 + 1); 
            for (int k=0; k < randArray.length;) {

                if(randArray[k] == randNum) {
                    k=0;
                // generate a random number only if the number exists in the array
                    randNum = (int)(Math.random() * 31 + 1); 
                } else { 
                   k++;   
                }
            }
            randArray[j] = randNum;
            System.out.println(j);
        }
0

Насколько мне известно, самый простой и эффективный способ создания (не очень большого) набора уникальных случайных чисел (он несколько похож на метод, предложенный Вирсабой):

1) генерировать ArrayList уникальных последовательных чисел, чтобы охватить весь необходимый диапазон
2) доступ к ArrayList с использованием случайного индекса и перемещение (получение и удаление из массива) записи в индексе.

Таким образом, после итераций ArrayList.size() вы получите результирующий массив уникальных случайных чисел.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню