Possible Duplicate:
Unique random numbers in O(1)?
How do I fill an integer array with unique values (no duplicates) in C?
int vektor[10];
for (i = 0; i < 10; i++) {
vektor[i] = rand() % 100 + 1;
}
//No uniqueness here
Possible Duplicate:
Unique random numbers in O(1)?
How do I fill an integer array with unique values (no duplicates) in C?
int vektor[10];
for (i = 0; i < 10; i++) {
vektor[i] = rand() % 100 + 1;
}
//No uniqueness here
I think this will do it (I've not tried to build it, so syntax errors are left to fix as an exercise for the reader). There might be more elegant ways, but this is the brute force solution:
One way would be to check if the array already contains the new random number, and if it does, make a new one and try again.
This opens up for the (random ;) ) possibility that you'd never get a number which is not in the array. Therefore you should count how many times you check if the number is already in the array, and if the count exceeds MAX_DUPLICATE_COUNT, throw an exception or so :) (EDIT, saw you're in C. Forget the exceptionpart :) Return an error code instead :P )
In your example (choose 10 unique random numbers between 1 and 100), you could create a list with the numbers 1 to 100, use the random number generator to shuffle the list, and then take the first 10 values from the list.
Based on cobbal's comment below, it is even better to just say:
Now it is O(N) to set up the list but O(M) to choose the random elements.
Here is an O(M) average-time method.
Method: If M <= N/2, use procedure S(M,N) (below) to generate result array R, and return R. If M > N/2, use procedure S(N-M,N) to generate R, then compute
X = {1..M}\R
[the complement of R in {1..M}], shuffle X with Fisher-Yates shuffle [in time O(M)], and return X.In the M > N/2 case, where O(M) == O(N), there are several fast ways to compute the complement. In the code shown below, for brevity I have only included an example of procedure S(M,N) coded inline in main(). Fisher-Yates shuffle is O(M) and is illustrated in main answer to related question #196017. Other previous related questions: #158716 and #54059.
The reason that S(M,N) takes O(M) time instead of O(N) time when M < N/2 is that, as described in Coupon-collector's problem the expectation E(t_k) is kH_k, from which E(t_{k/2}) = k(H_k - H_{k/2}) or about k*(ln(k)-ln(k/2)+O(1)) = k*(ln(k/(k/2))+O(1)) = k*(ln(2)+O(1)) = O(k).
Procedure S(k,N): [The body of this procedure is the dozen lines after the comment "Gen M distinct random numbers" in the code below.] Allocate and initialize three M+1-element integer arrays H, L, and V to all -1 values. For i=0 to M-1: Put a random value v into V[i] and into the sentinel node V[-1]. Get one of M list heads from H[v%M] and follow that list until finding a match to v. If the match is at V[-1] then v is a new value; so update list head H[v%M] and list link L[i]. If the match is not at V[-1], get and test another v, etc.
Each "follow the list" step has expected cost O(1) because at each step except the last, average list length is less than 1. (At end of processing, the M lists contain M elements, so average length gradually rises to exactly 1.)
Generate first and second digits separately. Shuffle them later if required. (syntax from memory)
However, the numbers will be nearly apart by n, 0 < n < 10.
Or else, you need to keep the numbers sorted (
O(n log n)
), so that newly generated can be quickly checked for presence (O(log n)
).i like the Floyd algorithm.
but we can take all the random number from
0
toM
(an not toin
) :