问题简述
给一个2面的硬币,要求设计一个算法来模拟6面骰子。
Follow Up:如何模拟任意[a, b]的均匀随机情况?其中a
思路阐述
首先明白一点,[a,b]的随机就等价于[0,b-a]的随机。
2面硬币只能产生0和1两种结果,N次之后可以产生一个N位的二进制数。例如3次之后可以随机出[0,7]的均匀随机情况。也就是说,如果b-a=2^N-1,那么抛N次硬币即可。
那么当b-a≠2^N-1呢?
考虑6面骰子,3次之后可能会有2个不符合的结果,因为6面骰子对应范围是[0,5],也就是说6和7这两个结果是不能用的。因此,采取策略如下:
- 抛3次硬币,假如结果在[0,5]内,直接使用结果;
- 假如结果是6或者7,则再抛3次硬币,直至产生有效结果。
推广至[0, b-a],也很类似。代码:
public static int uniformRandom(int lowerBound, int upperBound) {
int numberOfOutcomes = upperBound - lowerBound + 1, result;
do {
result = 0;
for (int i = 0; (1 << i) < numberOfOutcomes; ++i) {
// zeroOneRandom() is the provided random number generator.
result = (result << 1)|zeroOneRandom();
}
} while (result >= numberOfOutcomes);
return result + lowerBound;
}
总结
其实说穿了就很简单,但如果没遇到过,不一定一下子能想出来。