Java Math.random():
Returns a double
value with a positive sign, greater than or equal to 0.0
and less than 1.0
.
private static int randomWithRange(int min, int max) {
int range = max - min + 1;
return min + (int) (Math.random() * range);
}
因为 Math.random() 的范围是 >= 0 && < 1, 那么 Math.random() * max 肯定是小于 max. int 的强制转换是只保留整数,而不是做四舍五入. 所以
range = max - min + 1
否则 max 值永远取不到。
- Cracking the coding interview, 17.11
implement rand7() , given rand5()
rand5(), [0, 4]
rand7(), [0, 6]
public static int rand7() {
while (true) {
int num = 5 * rand5() + rand5();
if (num < 21) {
return num % 7;
}
}
}
- Cracking the coding interview, 18.2
shuffle deck, assume random generator is given
int rand(int min, int max) {
int range = max - min + 1;
return min + (int) (Math.random() * range);
}
void shuffle(int[] cards) {
for (int i = 0; i < cards.length; i++) {
int randPos = rand(0, i);
swap(cards, randPos, i);
}
}
- Cracking the coding interview, 18.3
randomly generate a set of m integers from an array of size n
int rand(int min, int max) {
int range = max - min + 1;
return min + (int) (Math.random() * range);
}
int[] pick(int orignal, int m) {
int subset = new int[m];
// fill in subset with first part of original
for (int i = 0; i < m; i++) {
subset[i] = orignal[i];
}
for (int i = m; i < orignal.length; i++) {
int k = rand(0, i);
if (k < m) {
subset[k] = orignal[i];
}
}
return subset;
}
随机2次,可能的结果有,00, 01, 10, 11。概率分别为:(1-p)*(1-p), (1-p)*p, p*(1-p), p*p。可以发现01和10的生成概率是相等的。因此让01代表0,10代表1,如果随机出了00或者11,就再随机2次。
- 有一个很大很大的输入流,大到没有存储器可以将其存储下来,而且只输入一次,如何从这个输入流中等概率随机取得m个记录。
这是一个蓄水池抽样问题
开辟一块容纳m个记录的内存区域,对于数据流的第n个记录,以m/n的概率将其留下(前m个先存入内存中,从第m+1个开始),随机替换m个已存在的记录中的一个,这样可以保证每个记录的最终被选取的概率都是相等的。
证明:设数据流中已经有n个记录流过,在内存中的m个记录中,假设都是等概率取得的,每个数命中的概率都为:mn。对于第n+1个记录,以mn+1的概率选中,如果没有选中,则内存中的m个记录均被留下来,每个数留下来其概率为:mn * (1-mn+1) = m(n+1-m)n(n+1);如果选中,新留下来的数概率自然是mn+1,而原来内存中的m个数中留下来m-1个数,每个数留下来的概率是:mn*mn+1*m-1m = m(m-1)n(n+1)。两种情况下概率之和为m(m-1)n(n+1)+m(n+1-m)n(n+1)=mn+1,即为原来被选中数,继续被选中的概率。由此我们不难得出,内存中每个数被选中概率一直都是mn。