Заполнение массива случайным числом

Я пытаюсь заполнить массив из 20 ints цифрами от 1-20 в случайной последовательности. здесь мой код:

 int lookup[20]={0}; 
 int array[20]={0};
 srand(time(NULL));
 for(int i=0;i<20;++i){ 
    bool done=false;
    while(!done){
      int n=rand()%20;
      if(lookup[n]==0){
          array[i]=n;
          lookup[n]=1;
          done=true;
      }
    }
 }

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

Ответ 1

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

Fisher-Yates shuffle: может быть сделано в O (n) времени.

Из Википедии:

Правильно реализовано, Shuffle Fisher-Yates беспристрастно, так что каждая перестановка одинаково вероятна. Современная версия алгоритма также достаточно эффективна, поэтому требуется только время, пропорциональное количеству перетасованных элементов и без дополнительного пространства для хранения.

Ответ 3

вы можете заполнить массив цифрами от 1 до 20 и использовать std:: random_shuffle

Заметьте, что вам не нужен вектор, если это будет простой массив.
Пример:

#include <iostream>
#include <algorithm>

using namespace std;

int main( void )
{
        int array[] = { 0, 1, 2, 3, 4 };

        srand( unsigned( time(NULL) ) );

        random_shuffle(array, array+5);

        for(int i=0; i<5; i++)
                cout << array[i] << endl;

        return 0;
}

Ответ 4

В этом коде есть возможность очень длинного цикла. Если вы находитесь в цикле while (! Done), нет никакой гарантии, что вы когда-нибудь закончите. Очевидно, что с массивом из 20 элементов это на практике не будет проблемой, но это может вызвать проблемы, если вы масштабируете это до многих тысяч элементов.

Более надежным решением было бы заполнить массив последовательно, а затем перетасовать его впоследствии.

Ответ 5

Я бы поместил 20 случайных чисел в массив, затем скопировал в другой массив из 20 элементов, отсортировал один массив и каждый номер в отсортированном массиве, нашел соответствующее число в несортированном массиве и поместил индекс там есть.

Ответ 6

Если вы можете использовать контейнеры, я бы просто заполнил std:: set цифрами от 1 до 20.

Затем вы можете вывести случайное число из вашего набора и вставить его в массив.

Ответ 7

что-то вроде этого?

int n = 20; //total element of array
int random = 0, temp=0, start=1;

for(int i=0; i < n; ++i,++start)
{
    array[i] = start;
}

for(int i=0; i<n ; ++i) 
{
    random=rand()%(n-i)+i;
    //swapping, you can make it as a function
    temp = array[i];
    array[i] = array [random];
    array[random] = temp; 

}

Ответ 8

Другой возможный способ

int array[20]={0};
int values[20];
for(int i = 0; i < 20; i++)
    values[i] = i;
int left = 20;
for(int i = 0; i < 20; i++)
{
    int n = rand() % left;
    array[i] = values[n];
    left--;
    values[n] = values[left];
}

PS заполняется номерами от 0 до 19 не от 1 до 20. То же, что оригинал

Ответ 9

Пример кода для Fisher-Yates:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void shuffle(int array[], size_t size)
{
    if(size) while(--size)
    {
        size_t current = (size_t)(rand() / (1.0 + RAND_MAX) * (size + 1));
        int tmp = array[current];
        array[current] = array[size];
        array[size] = tmp;
    }
}

int main(void)
{
    srand((int)time(NULL));
    rand(); // throw away first value: necessary for some implementations

    int array[] = { 1, 2, 3, 4, 5 };
    shuffle(array, sizeof array / sizeof *array);

    size_t i = 0;
    for(; i < sizeof array / sizeof *array; ++i)
        printf("%i\n", array[i]);

    return 0;
}

Ответ 10

Я надеюсь, что это поможет:

std::generate(array, array + sizeof(array)/sizeof(int), ::rand);

Ниже у вас есть полный код:

#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<iterator>

int main()
{
    int array[] = {1, 2, 3, 4};
    const unsigned SIZE = sizeof(array)/sizeof(int);

    cout << "Array before: ";
    std::copy(array, array+SIZE, std::ostream_iterator<int>(cout, ", "));

    std::generate(array, array+SIZE, ::rand); // answer for your question

    cout << "\nArray arter:  ";
    std::copy(array, array+SIZE, std::ostream_iterator<int>(cout, ", "));
}

Если вы хотите иметь меньшие числа, чем это, вы можете сделать это после генерации:

std::transform(array, array+SIZE, array, std::bind2nd(std::modulus<int>(), 255));