Generally, the process of generating random numbers does not consider repetition, because even repetition is normal in the probability sense. But in some cases, we need random data that is not repeated. what should we do? I think there should be only two methods. Sacrifice time or space.
Generally, the process of generating random numbers does not consider repetition, because even repetition is normal in the probability sense. But in some cases, we need random data that is not repeated. what should we do?
I think there should be only two methods. Sacrifice time or space.
In the following example ~ Within the range of 200 (set to B [100], which is actually an additional space), 10 random numbers (set to a [10]) are generated.
Sacrifice time
This method does not need to append the space B array.
To generate random numbers that cannot be repeated within a certain range, save the previously generated random numbers as historical data. After a new random number is generated, search for historical data. if a new random number is found, a new duplicate data search is generated. Otherwise, a new random number is found.
It is foreseeable that each new random number should be compared with all the preceding numbers. If repeated, discard and generate again; otherwise, generate the next one. The average time is n square magnitude.
Rough look, the above program seems to have no problem, the program can also pass during execution. However, after careful analysis, we will find that the problem lies in the determination of whether a new random number already exists. Since it is a random number, from a mathematical perspective, in terms of probability, the random number r generated each time may be the same. Although this possibility is very small, it is indeed a logic and correctness problem. Therefore, each new random number r may be one of the first I-1 number of the array random, that is, the program may lead to an endless loop during running!
Some may argue that this probability is very small, almost zero. Yes, but I want to ask what are the five major features of an algorithm, two of which are deterministic and poor.
So, how can this problem be solved? Sacrifice space.
Sacrifice space
The following method requires an array of space B.
Set a flag for each element of the array B [100] (B [I] = 100 + I, you may wish to set the array subscript from 1. Initially, all elements are flags = 0. If an element is selected into array a, flags = 1. Obviously, repeated elements can be selected later to determine whether the element is selected immediately. Does this mean that it is a space change time?
However, there is still a serious problem. in small-scale input, it is undoubtedly doing well. But here is an example of failure.
In 1 ~ Between 65536, select 65500 random numbers that are not repeated. Look at the following random number, for example, the number of 65,500th (the last one). it needs to select the remaining 36 numbers to have the flag = 0 (I don't know what these 36 numbers are); hum, the probability is 36/65536. As soon as it comes to the end, the more difficult it is to generate random numbers and the less time space it can take.
Improvement: first in 1 ~ Select 36 randomly from 65536 to delete. Assign the remaining 65500 numbers to a [65500] in sequence, and then disrupt the order.
When the size of the range array is very close to that of the target array, the preceding algorithm is very effective and is recommended.
In the first example, the initial array B [I] = 100 + I, array a is empty.
Each time a subscript of array B is randomly generated, the corresponding data a [subscript] is taken out, and written down. Then place the last number B [length] of array B to the position of subscript, and reduce the length of array a by 1. Although the subscript random numbers generated several times ago may be the same, because each time the last number is filled in, the numbers corresponding to the same subscript are never the same, and the numbers retrieved at a time are not the same. This ensures the algorithm's certainty, effectiveness, and poverty.
The following example describes how to generate a random number that is not repeated between 1 and 10.
Implemented through a while loop
A random number is generated continuously through the while loop until a non-repeating number is generated. this method is easy to think of, but the efficiency is also relatively low. the instance code is as follows:
static void Main(string[] args){int[] result = new int[10];int tmp = -1;Random random = new Random();bool repeat = false;for (int i = 0; i < 10; i++){ repeat = true; while (repeat) { repeat = false; tmp = random.Next(1, 11); for (int j = 0; j < i; j++) { if (tmp == result[j]) { repeat = true; break; } }}result[i] = tmp; }for (int i = 0; i < 10; i++)Console.WriteLine(result[i].ToString()); }
Implemented through the for loop
Method 1 uses multiple nested loops, which is very inefficient. Therefore, I apply certain skills to reduce nested loops to improve program efficiency. The main idea is to reduce the cyclic variable by 1 if the recurrence is detected, so as to re-execute a loop and re-generate a random number until a non-repeating random number is generated. the instance code is as follows:
Static void Main (string [] args) {int [] result = new int [10]; int tmp =-1; Random random = new Random (); bool repeat = false; for (int I = 0; I <10; I ++) {repeat = false; tmp = random. next (1, 11); for (int j = 0; j <I; j ++) {if (tmp = result [j]) {repeat = true; break;} if (! Repeat) {result [I] = tmp;} else {I = I-1; // cyclic variable-1 }}for (int I = 0; I <10; I ++) Console. writeLine (result [I]. toString ());}
This method reduces the number of nested loops and improves the efficiency.
Implemented by random sorting
This method completely subverts the basic ideas of methods 1 and 2. first, initialize an array containing numbers 1-10, and then take a random position for each loop, swap the element at this position with the element at the last position! The instance code is as follows:
static void Main(string[] args){int[] result = new int[10];for (int i = 0; i < 10; i++) result[i] = i + 1;for (int j = 9; j > 0; j--) { Random r = new Random(); int index = r.Next(0, j); int temp = result[index]; result[index] = result[j]; result[j] = temp;} for (int i = 0; i < 10; i++)Console.WriteLine(result[i].ToString());}
This method eliminates loop nesting and further improves the efficiency, but it also has some limitations. if you want to generate a random number between five groups of 1-10, this method of disordered order cannot be used.
Summary
- Method 1 is inefficient and is generally not recommended.
- Method 2 is more common, the efficiency is higher than method 1, but the efficiency is lower than method 3.
- Method 3, although highly efficient, can only be applied to specific situations.
The main idea of the following example is that if the number already exists, the number of loops is removed and regenerated.
Void static Main () {Random random = new Random (); bool repeat = true; int temp; int [] store = new int [10]; for (int I = 0; I <10; I ++) {temp = random. next (1, 11); for (int j = 0; j
If the number of random numbers to be generated is relatively small, you can store all the numbers in the array first, and then randomly swap the numbers in the array:
Static void Main () {int [] store = new store [10]; // defines an array and initializes for (int I = 1; I <11; I ++) // assign the array by looping {store [i-1] = I;} for (int j = 9; j> 0; j --) {Random r = new Random (); int index = r. next (0, j); // int index = r. next (); I think there are some problems. Int temp = store [index]; store [index] = store [j]; store [j] = temp ;}}
This article is available at http://www.nowamagic.net/librarys/veda/detail/510.