如何高效产生m个n范围内的不重复随机数(m<=n)
最近看到一道算法题,如何取100以内不重复的100个随机数?答案如下:
|
|
个人感觉题目很经典,实际生活中会经常遇到类似问题,但答案却如此低效,不免有一些失望,打开vs试了一把,果然2分钟都没跑完。
如果用上面的算法,把m、n放大到10000,估计程序1天都跑不完,效率令人发指。百度一下,发现《编程珠玑》一书收录该算法,题目为“如何高效产生m个n范围内的不重复随机数(m<=n)”。
那么该书中是如何解决该问题的呢?答案如下:
|
|
该算法非常巧妙的取随机数的位置(数组的下标),替代取随机数本身,每次取到一个随机数之后,就将其在取值范围中排除,下一次仅会在剩下的数字中取,一次遍历就可以完成随机数的选取,效率相当高。
算法详细分析:
- 为数组的每个数字按其位置(数组的下标)赋值,我们获得一个 100个数字、顺序排列 的数组。
- 开始取 i-99 范内的随机数,把每次取到的随机数作为位置(数组的下标)与位置(数组的下标)为 i 的数交换数值。这样做的意义是,将已经取到的随机数在取值范围中排除,下一次去随机数仅会在剩下的数字中取。
第2步不太容易理解,举个栗子:假设第一次取到的随机数是39,把 位置39的数 与 位置0的数 交换之后,再从 位置1 开始看该数组,你会惊奇的发现,剩下的是0-99除39以外的所有数字,但它们的位置是1-99,接下来我们仅需要从1-99中取一个随机数,作为数组下标,即可在剩下的数字中取随机数了,以此类推。