Random array generation with no duplicates

前端 未结 9 904
無奈伤痛
無奈伤痛 2020-11-28 12:48

I am trying to create something that generates a random array with no duplicate values. I\'ve already looked at other answers but none seem to help me understand. I cannot t

相关标签:
9条回答
  • 2020-11-28 12:48

    There are 2 solutions to choose from:

    1. Generate random numbers using something like rand() and check for duplicates.

    2. Find a mathematical sequence that is strictly monotonic (preferably strictly increasing) and get its terms as members of your array. Then, you can shuffle your array. The result will not be truly random, but neither using rand() won't. rand() uses a simillar tehnique, and that is why we need to set the seed with something changeing, like time. You can use time for example to generate the first element of the sequence, and with a good sequence your results will be at least decent. Note that the sequence MUST be strictly monotonic, to avoid generation of duplicates. The sequence need not be too complex. For example, if you get unix time modulo 10000 as the first term and then you generate other terms using a reccurence like x[i] = x[i-1] + 3*x[i-2] should be fine. Of course, you may use more sophisticated sequences too, but be careful at overflow (as you can't apply modulo operator to the result, because it would not be increasing anymore) and the number of digits you would like to have.

    0 讨论(0)
  • 2020-11-28 12:49

    In c++, all you need is:

    std::random_shuffle()
    

    http://www.cplusplus.com/reference/algorithm/random_shuffle/

    int numbers [4];
    
    for (int x=0; x!=4;x++)
    {
        numbers[x] = x;
    }
    
    std::random_shuffle(numbers, numbers +4);
    

    Update: OK, I had been thinking that a suitable map function could go from each index to a random number, but thinking again I realize that may be hard. The following should work:

        int size = 10;
        int range = 100;
    
        std::set<int> sample;
    
        while(sample.size() != size)
            sample.insert(rand() % range); // Or whatever random source.
    
        std::vector<int> result(sample.begin(), sample.end());
    
        std::random_shuffle ( result.begin(), result.end() );
    
    0 讨论(0)
  • 2020-11-28 12:49

    After you generate each random number, loop through the previous values and compare. If there's a match, re-generate a new value and try again.

    0 讨论(0)
  • 2020-11-28 12:51

    You can use your own random number generator which has the sequence greater or equal to length of the array. Refer to http://en.wikipedia.org/wiki/Linear_congruential_generator#Period_length for instructions.

    So you need LCG with expression Xn+1 = (aXn + c) mod m. Value m must be at least as large as length of the array. Check "if and only if" conditions for maximum sequence length and make sure that your numbers satisfy them.

    As a result, you will be able to generate random numbers with satisfactory randomness for most uses, which is guaranteed to not repeat any number in the first m calls.

    0 讨论(0)
  • 2020-11-28 13:04

    First of all rand() is generatig random numbers but not wihout duplicates.

    If you want to generate a random array without duplicates the rand() method is not working at all.

    Let say you want to generate an array of 1000 numbers. In the best case let say you generated the first 999 numbers without duplicates and last think to do is generating the last number. The probability of getting that number is 1/1000 so this is almost going to take forever to get generated. In practice only 10 numbers makes a big trouble.

    The best method is to generate all your numbers by incrementation (or strictly monotonic sequence) is shuffle them. In this case there will be no duplicates

    Here is an exemple on how to do it with 10 numbers. Even with 1000 numbers it's working.

    Note: Suffle function from Jhon Leehey's answer.

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    void shuffle(int *arr, size_t n)
    {
        if (n > 1) 
        {
            size_t i;
            srand(time(NULL));
            for (i = 0; i < n - 1; i++) 
            {
              size_t j = i + rand() / (RAND_MAX / (n - i) + 1);
              int t = arr[j];
              arr[j] = arr[i];
              arr[i] = t;
            }
        }
    }
    
    int main()
    {
        int i;
        int arr[10];
        for (i=0; i<10; i++){
            arr[i] = i;
        }
        shuffle(arr, 10);
        for (i=0; i<10; i++){
            printf("%d ", arr[i]);
        }
    }
    
    0 讨论(0)
  • 2020-11-28 13:07

    How about this:

    #define NUMS (10)
    
    int randomSequence[NUMS] = {0}, i = 0, randomNum; 
    bool numExists[NUMS] = {false};
    
    while(i != NUMS)
    {
        randomNum = rand() % NUMS;
    
        if(numExists[randomNum] == false)
        {
            randomSequence[i++] = randomNum;
            numExists[randomNum] = true;
        }
    }
    

    Of course, the bigger NUMS is, the longer it will take to execute the while loop.

    0 讨论(0)
提交回复
热议问题