随机数 生成时间要平均
安全维护
生成随机数组,在很多领域的开发中都会用到,例如游戏开发。随机数组生成的时间如果是固定的,那么执行效率就比较高;如果不固定,就可能会影响程序的运行速度。所以,在招聘考试中,一定会有生成随机数组的题目。
招聘题目:生成20个随机数字,该组数字中包含2组1~10之间的整数,即包含2个1、2个2,依此类推,但是每个数字的位置是随机的。
答案A:
int num[] = new int[20];
int index = 0; //数组下标
int ranNum; //随机数字
int time = 0; //数字已出现次数
Random r = new Random();
while(true){
ranNum = r.nextInt(9) + 1; //随机1~10之间的数字
//统计数字ranNum已出现次数
time = 0;
for(int i = 0;i < index;i++){
if(num[i] == ranNum){
time++;
}
}
//如果未出现2次
if(time != 2){
num[index] = ranNum;
index++; //继续赋值下一个
}
if(index == num.length){ //全部赋值
break;
}
}
答案B:
//生成2组1~10之间的规则数字
int num[] = new int[20];
for(int i = 0;i < num.length;i++){
num[i] = i / 2 + 1;
}
//随机打乱数字顺序
Random r = new Random();
int times = 30; //两两交换次数
int ranIndex; //随机下标
int temp; //交换变量
int cIndex; //当前下标
for(int i = 0;i < times;i++){
ranIndex = r.nextInt(20); //[0~20]之间的随机数,作为下标
//和下标i % 20交换
cIndex = i % 20;
if(cIndex != ranIndex){
temp = num[cIndex];
num[cIndex] = num[ranIndex];
num[ranIndex] = temp;
}
}
正确答案:B
答案分析
答案A使用的是自然思维,即随机生成一个1~10之间的数字,然后判断该数字是否已在数组中出现2次,如果未出现2次,则将该数字赋值到数组中,接着随机出现下一个数字。使用这种方式,虽然可以满足要求的功能,但是在程序的执行效率上很不稳定,每次随机过程所需时间的差异很大,甚至有可能卡死。如果程序中生成较多的随机数字,那么就不能用这种方法。
答案B采用的是一种变通的方法,先生成一组规则的数字,然后随机打乱改组数字的顺序。使用这种思路,程序的执行效率很稳定,而且实现起来比较简单。具体步骤如下:生成两组1~10之间的整数,按照1,1,2,2,……的顺序依次赋值到数组中,这样就得到一个规则的数组num。
接着使用两两交换的方式随机交换数组中数字的位置,生成一个随机数字,作为一个数组交换时的下标,然后和数组当前的下标进行交换,这样经过一定次数的交换以后,数组中的数字位置就变得随机了。每次交换消耗的时间基本固定,代码的执行效率很稳定,生成的速度也很高效。
扑克洗牌中的随机数组
高效生成随机数组,这种算法在实际的程序开发中大量被使用,特别是在游戏中被广泛使用,例如扑克游戏中的洗牌,网游中的随机掉装备等。下面,我们来看看在实际程序开发中是如何高效生成随机数组的。
代码的目的是要实现扑克游戏洗牌的功能,根据扑克牌的特点(每副牌包含54张不同的牌),将扑克牌中的每张牌依次对应编号成0~53之间的整数,那么一副牌就是一个包含0~53之间所有整数的数组,而洗牌就是将这样一个规则的数组变成一个随机数组。代码如下所示:
//生成一副牌,编号为0~53
int poker[] = new int[54];
for(int i = 0;i < poker.length;i++){
poker[i] = i;
}
//洗牌
Random r = new Random();
int times = 54; //两两交换次数
int ranIndex; //随机下标
int temp; //交换数字
int cIndex; //当前下标
for(int i = 0;i < times;i++){
ranIndex = r.nextInt(54); //[0~53]之间的随机数
//和下标i % 54交换
cIndex = i % 54;
if(cIndex != ranIndex){
temp = poker[cIndex];
poker[cIndex] = poker[ranIndex];
poker[ranIndex] = temp;
点评:在该代码中,先生成一个包含[0,53]之间所有整数的规则数组poker,然后再使用两两交换的方式对该数组中的元素交换54次。