1. The most austere practice of violence.
voidCal1 () {inti =0, j =0, num =0; intResult[m]; result[0] = rand ()% N;//The first one is definitely not repeated, just add it in. for(i =1; i < M; i++)//Get the remaining (M-1) random number{num= rand ()% N;//generate random numbers between 0 and N for(j =0; J < I; J + +) { if(num = = Result[j])//if one of the elements in the result array is duplicated{i--;//start this cycle again Break; } } if(j = = i)//indicates that the original elements in the newly generated number and array are different, then add in{Result[i]=num; } }}
2. On the basis of Method 1 we can optimize. Each round of n is too time-consuming to optimize to Logn, so use set as a helper, in order to take advantage of its logn time complexity. The price is more space for a set of M size.
void Cal2 () { set <int > S; int num = 0 , index = 0 ; int Result[m]; while (Index < M) {num = RA nd ()% N; if (s.find (num) = = S.end ()) // Span style= "color: #008000;" > If you do not find {S.insert (num); Result[index + +] = num; } }}
3. If you are bored by the repetition of methods 1 and 2, it may be thought that each new random number will be compared with the existing number to compare whether it already exists, and the lower the efficiency of the method, the less efficient, and constantly do not work hard. What about the way it's done? A few pounds a few two we are on the board, OK, all the numbers are listed first, from the inside of the screening, then each election, it is certainly not repeated. You just have to choose m times.
voidCal3 () {intResult[m] = {0}; Deque<int> Deq;<span style="White-space:pre"> </span>//Queue inti =0, index; <span style="White-space:pre"> </span> for(i =0; i < N; i++)//Initialize, put all n number in the container, from here to the outside to pick, each time will not repeat{deq.push_back (i); } for(i =0; i < M; i++)//Select the number of M{Index= rand ()% deq.size ();//Note that deq.size () is constantly getting smaller, but each time it meets random characteristicsResult[i] = deq.at (index);//assigns the element of the DEQ array index position to Result[i]Deq.erase (Deq.begin () + index);//Remove the element from the DEQ queue }}
4. Method 3 is the idea of a more idealistic and direct, in practice, you will find a lot slower than the method 1, the reason is in the container of the erase function, the internal implementation of the essence is a copy of the memory slice, this operation is quite time-consuming. This is not about language, but in other languages such as Java, Similar functions are the same principle. In fact, thinking about Method 3, the truth is ready. We continue to refine the algorithm along this line of thinking. The idea of removing elements from them is good, but the method is poor. In fact, we need is the basic array can be, the speed is fast, with deque, vector these containers are nothing more than to use their erase function to eliminate a number of the next random process. With a number of selected, the size of the container is also constantly smaller, in fact , using an array, using the subscript offset, we can do it directly! and using an array to implement a queue or stack is not the same, nothing but the array subscript move! So along the idea of Method 3, each time we randomly come out a subscript index (0 <= Index < size (size initial value is N)), each time the element of Arr[index] This position is thrown to the last side of the array, it is equivalent to culling operation!
voidCal4 () {intResult[m] = {0}; intData[n] = {0}; inti =0, index =0; for(i =0; i < N; i++)//Initialize{Data[i]=i; } for(i =0; i < M; i++) {Index= rand ()% (N-i); Result[i]= Data[index];//assigns the element of the data array index position to Result[i]Data[index] = data[n-i-1];//from the end of the data array (this position is constantly moving forward) take a number to that position, which is equivalent to the element being rejected. }}
Performance test:
http://blog.csdn.net/aa2650/article/details/12507817
Direct output:
How to generate m non-repeating numbers between 0 and N with a random number
1, the most direct method is to randomly generate a number between 0 to N, determine whether the number has been selected, if not previously selected, then select, if previously selected, discard
[CPP]View Plaincopy
- void Common (int n,int m)
- {
- int * randnum= (int *) malloc (nsizeof (int));
- memset (randnum,0,n*sizeof (int)); //Put all n positions 0
- Srand (Time (NULL));
- While (m)
- {
- int Cur=rand ()%n;
- if (randnum[cur]==0) //To determine if the current number is not selected, then select and output
- {
- cout<<cur<<endl;
- Randnum[cur]=1;
- m--;
- }
- }
- Free (randnum);
- }
This method is easy to understand, but it takes extra space to make sure that the number is not duplicated, so we have no easier way, the answer is yes
2, first on the code, after doing the explanation
[CPP]View Plaincopy
- void Mrand (int n,int m)
- {
- Srand (Time (NULL));
- For (int i=0;i<n;i++)
- {
- if (rand ()% (n-i) <m)
- {
- cout<<i<<endl;
- m--;
- }
- }
- }
The code above is concise, but it's not easy to understand, so let's explain
The first is a loop, which ensures that the number of outputs is not duplicated, because I is different every time.
The second is the number of M, in each cycle will use RAND ()% (n-i) <m to determine whether this number is less than m, if the conditions of the M minus 1, until 0, indicating that the number of M has been taken
Again is how to ensure that the number of M is equal to the probability of taking
In the first loop, i=0, N-i=n, the random number generates a random number between 0-n-1, then the probability of 0 being taken is m/n-1
I=1,n-i=n-1 in the second loop, the random number generates a random number between 0-n-2, at which point the probability of 1 being taken is related to the last cycle of 0. Assuming that there is no fetch in the last loop, the probability of 1 is m/n-2; assuming that the last cycle has been taken, the probability of taking 1 is m-1/n-2, so the probability of this being taken in general is (1-m/n-1) * (m/n-2) + (m/n-1) * (m-1/ N-2), the final-pass merge results in the same m/n-1 as the first probability
Similarly, in the first I cycle, I is taken to the probability of m/n-1
So the m number is equal to the probability of being taken.
Reference: http://blog.csdn.net/dlengong/article/details/7932579
Spin: Randomly generate an array of length m (M <= N) and non-repeating content within the range of 0~n (excluding N)