题目:有一个方法(fiveRandom)随机返回一个1-5的平均概率的integer。
public static int fiveRandom(){
return new Random().nextInt(5)+1;
}
要求从该方法得到结果后,最后输出一个1-7的平均概率的integer。
本人的思路:从5变成7,那么就要知道最小公因数是多少(5*7=35),没错,就是35,那么接下来继续思考,从5变成7,可以把1-5的每个数,都看成为7组合的一组数据,把1-7的每个数看成5组合的一组数据,这样就能让1-5的每个数,转成1-7的每个数字且概率相等。
接下来分析规律,列出如下的1-5对应的1-7的数据。
/**
* 1 -> 1(5),2(2) 7
* 2 -> 2(3),3(4) 14
* 3 -> 3(1),4(5),5(1) 21
* 4 -> 5(4),6(3) 28
* 5 -> 6(2),7(5) 35
* 6 -> 7(2),8(5)
* 7 -> 8(2),9(5)
* ..... 无线的
*/
显而易见,1-5的15=7,27=14.
我们能发现7%5 = 2,14%5=4;这样规律也出来了,7对应的余数为2,刚好随机数为1的情况下,1到7的区间内,包含了1和2两个数的概率,且为1的概率为5/7,为2的概率为2/7;
同理,当随机数为2时,会出现2和3两个数的随机,2的概率为3,3的概率为4;
能发现,除以5的余数和最后一位的概率相等。
现在知道了当前对应的数字最后一位的概率,再来思考每个随机数会出现对应的数字有哪些:我们得知,1-7对应的每个数字,都拆分为5个数字。那么可以得出最大数字为17/5来计算;如果出现除不尽,且有余数的时候,则证明必定有指向下一个数字。那么可以得到最大值为17/5+1;
这样,最大值,以及最大值的概率都得到了,那么接下来继续思考如何得出正确的概率结果呢?
经过思考,我们得知,1-5每个数字都对应了7个数,唯一的区别就是这7个数,对应的值和概率;但是值和概率,上面已经到手了,那么开始编写代码吧。
private static Integer random(Integer i) {
// if (i < 1 || i > 5) {
// throw new IllegalArgumentException();
// }
/**
* 1 -> 1(5),2(2) 7
* 2 -> 2(3),3(4) 14
* 3 -> 3(1),4(5),5(1) 21
* 4 -> 5(4),6(3) 28
* 5 -> 6(2),7(5) 35
* 6 -> 7(2),8(5)
* 7 -> 8(2),9(5)
* ..... 无线的
*/
int max = i * 7; //求出最大的随机数
int maxRes = (maxRes = max % 5) == 0 ? 5 : maxRes; // 最大随机数/5 的余数
int subMax = 5 == maxRes ? max / 5 : (max / 5) + 1; // 区间最大值
int subSize = maxRes == 1 ? 3 : 2; // 区间有几位
int tempSize = subSize;
int seven = 7;
int bit = 7;
int min;
int rand = new Random().nextInt(7) + 1; //必须大于0
// 填充位数
for (int i1 = 0; i1 < subSize; i1++) {
min = (seven -= 0 == i1 ? maxRes : Math.min(seven, 5));
if (bit >= rand && min < rand) {
return subMax;
}
bit = seven;
subMax--;
}
return -1;
}
public static void main(String[] args) {
Map<Integer, Integer> fiveMap = new HashMap<>();
Map<Integer, Integer> sevenMap = new HashMap<>();
int res;
for (int i = 0; i < 1000000; i++) {
res = maxRandom(5);
fiveMap.put(res, fiveMap.getOrDefault(res, 0) + 1);
sevenMap.put(res = random(res), sevenMap.getOrDefault(res, 0) + 1);
}
System.out.println(fiveMap.toString());
System.out.println(sevenMap.toString());
}