之前看到一个算法题“用已有的rank7()函数生成rank10()函数”,看到了各种思路,不过看到一个可以用rankn()函数生成任意rankm()的通用方法比较有意思,就实现了一下记了下来。
该思路就是,首先用已有的rank7()生成随机数1-7,然后如果生成了1-3就返回0,生成了4-6就返回1,生成了7就重新生成。这样就把生成7个随机数变成等概率生成0或1。
然后用0和1生成一个4位的二进制数(因为 < 10 <
),因为每一位出现0和1的概率是相同的,所以从0000到1111这16个数字的概率也是相同的,然后用0000~1001这10个数分别对应1-10即可,如果生成了其他数就递归调用。
看代码:
import java.util.Random;
class Solution{
//循环四轮生成0000-1111二进制数并转换成1-10输出
public static int rand10() {
int a = 0;
for(int i = 0;i < 4;i++){
a *= 2;
a += rand2();
}
return a>9? rand10() : a+1;
}
//将7个随机数变成等概率生成0/1
public static int rand2(){
int a = rand7();
return a == 7? rand2() : a/4;
}
//用自带的rand7生成1-7随机数
public static int rand7(){
Random r = new Random();
return r.nextInt(7) + 1;
}
public static void main(String args[])
{
int array[] = new int[10];//用数组统计1-10的数量
for(int i = 0;i < 10;i++){
array[i] = 0;
}
//生成1000000个数,统计数量
for(int i = 0;i < 1000000;i++){
array[rand10() - 1] += 1;
}
for(int i = 0;i < 10;i++){
System.out.println((i+1) + "的数量:" + array[i]);
}
}
}
代码运行了3次,可以看到每次运行后生成10个数的数量差不多在10万左右
1的数量:99878
2的数量:100396
3的数量:99849
4的数量:100147
5的数量:100456
6的数量:99673
7的数量:99534
8的数量:100120
9的数量:99665
10的数量:100282
--------------------------------
1的数量:99517
2的数量:99800
3的数量:100175
4的数量:100146
5的数量:99990
6的数量:99844
7的数量:100204
8的数量:100163
9的数量:100214
10的数量:99947
---------------------------------
1的数量:100387
2的数量:99460
3的数量:99874
4的数量:100296
5的数量:100181
6的数量:100154
7的数量:99717
8的数量:99685
9的数量:100206
10的数量:100040