随机地生成n个不超过n且不重复的正整数
2015-05-10 15:36
447 查看
许久以前,参加校园招聘,在面试时被问到“如何随机地生成n个不超过n且不重复的正整数”。你会怎么做呢?n的值具体是多少并不重要,我们关心的重点是如何在n确定时设计一种法案来解决随机产生不重复的数的问题。下面就以n =100为例来说明几种实现方式,将产生的随机数存放于数组中。
方案1.
话说当时见识少,功夫不到家,认为每次随机生成数字,再判断该数字是否已经重复,如果不重复则保留该值,否则重新产生新的随机数字。
该方法能实现我们所需要完成的功能,但是稍微想想,这种方式效率非常低,每次生成随机数后都需要判断是否和已产生的随机数重复,需要耗费n的时间复杂度,并且越往后重复的概率越大,当前面生成了n-1个数,需要产生第n个数时,可能需要产生几十个数,每次产生都需要查重,导致生成一个数可能耗费成千上万次运算。
方案2.
再来思考一下题目:随机产生n个不超过n的不重复的数字,不就是将0到n-1的n个数的顺序打乱么。
首先初始化数组,按序填充数组,接下来就是随机改变数组中元素的位置。如何改变数组中元素的位置,最简单的方式就是随机产生两个数,交换以这两个数为下标的元素。
该方案相对方案一简洁了许多,时间复杂度降低了许多。但是在仔细想一想,是最好的么,能否再进行优化?
方案3.
将code从前往后仔细读了几次,存在着两个小疑惑:1.能不能每次只产生一个随机数?2.很有可能有些位置上的元素被交换了好几次,但有些位置上的元素一次也不进行交换,能否确保每个位置上的元素都被交换?
思考到这里,这似乎是最简洁的方式了。隐隐觉得还有所欠缺,但没能想到解决方案。最近看到编程珠玑上有一种新的解法,盛是精辟。
每次产生不大于i的数,将以该数字为下标的元素和以i为下标的元素进行交换,确保位子全部被调换,又比上面的发法巧妙多了(没有随机排序的概率小多了)。
许久以前,参加校园招聘,在面试时被问到“如何随机地生成n个不超过n且不重复的正整数”。你会怎么做呢?n的值具体是多少并不重要,我们关心的重点是如何在n确定时设计一种法案来解决随机产生不重复的数的问题。下面就以n =100为例来说明几种实现方式,将产生的随机数存放于数组中。
方案1.
话说当时见识少,功夫不到家,认为每次随机生成数字,再判断该数字是否已经重复,如果不重复则保留该值,否则重新产生新的随机数字。
import java.util.Random; public classGenerateRandom { static final int Number= 100; public static voidmain(String[] args) { int[] Data = new int[Number]; GenRandom1(Data); } private static voidGenRandom1(int[] In_Array) { for(int i = 0; i < Number; i++) { In_Array[i] = -1; //初始化 } Random random = newRandom(); int count = 0; //count用来控制生成n个数 while(count < Number) { int index = random.nextInt(Number-1);//随机生成小于n的数 int i = 0; for(i = 0; i < Number; i++) {//查重 if(In_Array[i] == index) break; } if(i == Number) { //i小于n时表明已重复,否则不重复 In_Array[count] = index; count++; } index = random.nextInt(Number); } } }
该方法能实现我们所需要完成的功能,但是稍微想想,这种方式效率非常低,每次生成随机数后都需要判断是否和已产生的随机数重复,需要耗费n的时间复杂度,并且越往后重复的概率越大,当前面生成了n-1个数,需要产生第n个数时,可能需要产生几十个数,每次产生都需要查重,导致生成一个数可能耗费成千上万次运算。
方案2.
再来思考一下题目:随机产生n个不超过n的不重复的数字,不就是将0到n-1的n个数的顺序打乱么。
首先初始化数组,按序填充数组,接下来就是随机改变数组中元素的位置。如何改变数组中元素的位置,最简单的方式就是随机产生两个数,交换以这两个数为下标的元素。
private static voidGeneRandom2(int[] In_Array) { for(inti = 0; i < Number; i++) { In_Array[i] = i; } Random random = newRandom(); for(int i = 0; i < Number; i++) { intr1 = random.nextInt(Number- 1); intr2 = random.nextInt(Number- 1); if(r1 != r2) { inttemp = In_Array[r1]; In_Array[r1] = In_Array[r2]; In_Array[r2] = temp; } } }
该方案相对方案一简洁了许多,时间复杂度降低了许多。但是在仔细想一想,是最好的么,能否再进行优化?
方案3.
将code从前往后仔细读了几次,存在着两个小疑惑:1.能不能每次只产生一个随机数?2.很有可能有些位置上的元素被交换了好几次,但有些位置上的元素一次也不进行交换,能否确保每个位置上的元素都被交换?
for(inti = 0; i < Number; i++) { intr1 = random.nextInt(Number- 1); if(r1 != i) { inttemp = In_Array[r1]; In_Array[r1] = In_Array[i]; In_Array[i] = temp; } }
思考到这里,这似乎是最简洁的方式了。隐隐觉得还有所欠缺,但没能想到解决方案。最近看到编程珠玑上有一种新的解法,盛是精辟。
Random random = newRandom(); for(int i = Number- 1; i > 0; i--) { int index = random.nextInt(i); inttemp = In_Array[index]; In_Array[index] = In_Array[i]; In_Array[i] = temp; }
每次产生不大于i的数,将以该数字为下标的元素和以i为下标的元素进行交换,确保位子全部被调换,又比上面的发法巧妙多了(没有随机排序的概率小多了)。
相关文章推荐
- 快速生成大量指定位数的不重复随机整数
- c#部分---网吧充值系统;简易的闹钟;出租车计费;简单计算器;对战游戏;等额本金法计算贷款还款利息等;随机生成10个不重复的50以内的整数;推箱子;
- Java简单易懂的生成不重复随机整数数组的方法
- 生成1亿个不重复的8位随机整数
- 随机生成0~N之间的N个不重复整数
- 随机生成十个不重复的整数
- 随机生成0~N之间的N个不重复整数
- 生成不重复的随机整数
- 明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤1000),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从
- 随机生成不重复的整数(随机洗牌函数)
- 随机生成十个不重复的整数
- 随机生成n个不重复的正整数
- 如何生成[0,maxval]范围内m个随机整数的无重复的有序序列
- matlab中生成无重复随机整数的方法
- 【Java】随机生成范围[min,max]之间的整数数组,且元素值不重复
- 随机生成不重复的整数
- c 生成随机不重复的整数序列
- js 生成两个整数之间不重复的n个随机整数
- 随机生成10个不重复的整数
- 随机生成10个不重复的整数