题目:

已知一个函数rand7()能够生成1-7的随机数,请给出一个函数,该函数能够生成1-10的随机数。

思路:

假如已知一个函数能够生成1-49的随机数,那么如何以此生成1-10的随机数呢?

解法:

该解法基于一种叫做拒绝采样的方法。主要思想是只要产生一个目标范围内的随机数,则直接返回。如果产生的随机数不在目标范围内,则丢弃该值,重新取样。由于目标范围内的数字被选中的概率相等,这样一个均匀的分布生成了。

显然rand7至少需要执行2次,否则产生不了1-10的数字。通过运行rand7两次,可以生成1-49的整数,

   1  2  3  4  5  6  7
1 1 2 3 4 5 6 7
2 8 9 10 1 2 3 4
3 5 6 7 8 9 10 1
4 2 3 4 5 6 7 8
5 9 10 1 2 3 4 5
6 6 7 8 9 10 * *
7 * * * * * * *

由于49不是10的倍数,所以我们需要丢弃一些值,我们想要的数字范围为1-40,不在此范围则丢弃并重新取样。

代码:

  1. int rand10() {
  2. int row, col, idx;
  3. do {
  4. row = rand7();
  5. col = rand7();
  6. idx = col + (row-1)*7;
  7. } while (idx > 40);
  8. return 1 + (idx-1)%10;
  9. }

由于row范围为1-7,col范围为1-7,这样idx值范围为1-49。大于40的值被丢弃,这样剩下1-40范围内的数字,通过取模返回。下面计算一下得到一个满足1-40范围的数需要进行取样的次数的期望值:

E(# calls to rand7) = 2 * (40/49) +
4 * (9/49) * (40/49) +
6 * (9/49)2 * (40/49) +
...
= ∑ 2k * (9/49)k-1 * (40/49)
k=1 = (80/49) / (1 - 9/49)2
= 2.45

优化:

上面的方法大概需要2.45次调用rand7函数才能得到1个1-10范围的数,下面可以进行再度优化。

对于大于40的数,我们不必马上丢弃,可以对41-49的数减去40可得到1-9的随机数,而rand7可生成1-7的随机数,这样可以生成1-63的随机数。对于1-60我们可以直接返回,而61-63则丢弃,这样需要丢弃的数只有3个,相比前面的9个,效率有所提高。而对于61-63的数,减去60后为1-3,rand7产生1-7,这样可以再度利用产生1-21的数,对于1-20我们则直接返回,对于21则丢弃。这时,丢弃的数就只有1个了,优化又进一步。当然这里面对rand7的调用次数也是增加了的。代码如下:

  1. int rand10Imp() {
  2. int a, b, idx;
  3. while (true) {
  4. a = rand7();
  5. b = rand7();
  6. idx = b + (a-1)*7;
  7. if (idx <= 40)
  8. return 1 + (idx-1)%10;
  9. a = idx-40;
  10. b = rand7();
  11. // get uniform dist from 1 - 63
  12. idx = b + (a-1)*7;
  13. if (idx <= 60)
  14. return 1 + (idx-1)%10;
  15. a = idx-60;
  16. b = rand7();
  17. // get uniform dist from 1-21
  18. idx = b + (a-1)*7;
  19. if (idx <= 20)
  20. return 1 + (idx-1)%10;
  21. }
  22. }

下面计算下优化后方法的调用rand7函数的期望次数:

E(# calls to rand7) = 2 * (40/49) +
3 * (9/49) * (60/63) +
4 * (9/49) * (3/63) * (20/21) + (9/49) * (3/63) * (1/21) *
[ 6 * (40/49) +
7 * (9/49) * (60/63) +
8 * (9/49) * (3/63) * (20/21) ] + ((9/49) * (3/63) * (1/21))2 *
[ 10 * (40/49) +
11 * (9/49) * (60/63) +
12 * (9/49) * (3/63) * (20/21) ] +
... = 2.2123

这里期望次数为2.21,比起未优化的2.45次减少了大概10%。

已知一个函数rand7()能够生成1-7的随机数,请给出一个函数rand10(),该函数能够生成1-10的随机数。的更多相关文章

  1. JAVA-集合作业-已知有十六支男子足球队参加2008 北京奥运会。写一个程序,把这16 支球队随机分为4 个组。采用List集合和随机数

    第二题 已知有十六支男子足球队参加2008 北京奥运会.写一个程序,把这16 支球队随机分为4 个组.采用List集合和随机数 2008 北京奥运会男足参赛国家: 科特迪瓦,阿根廷,澳大利亚,塞尔维亚 ...

  2. 找出数组中出现次数超过一半的数,现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数

    找出数组中出现次数超过一半的数,现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数 #include<iostream>using namespace s ...

  3. 最短路径(给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 说明:每次只能向下或者向右移动一步。)

    给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 例: 输入: [ [1,3,1], [1,5,1], [ ...

  4. 请写出一个超链接,点击链接后可以向zhangsan@d-heaven.com发送电子邮件。

    请写出一个超链接,点击链接后可以向zhangsan@d-heaven.com发送电子邮件. <a href=”mailto: zhangsan@d-heaven.com”>发邮件</ ...

  5. 第二题 已知有十六支男子足球队参加2008 北京奥运会。写一个程序,把这16 支球队随机分为4 个组。采用List集合和随机数 2008 北京奥运会男足参赛国家: 科特迪瓦,阿根廷,澳大利亚,塞尔维亚,荷兰,尼日利亚、日本,美国,中国,新西 兰,巴西,比利时,韩国,喀麦隆,洪都拉斯,意大利

    package com.hanqi.test; import java.util.ArrayList; import java.util.List; import java.util.Random; ...

  6. 已知有十六支男子足球队参加2008 北京奥运会。写一个程序,把这16 支球队随机分为4 个组。采用List集合和随机数

      package homework002; import java.util.ArrayList; import java.util.List; import java.util.Random; p ...

  7. 第二题 已知有十六支男子足球队参加2008 北京奥运会。写一个程序,把这16 支球队随机分为4 个组。采用List集合和随机数     2008 北京奥运会男足参赛国家:  科特迪瓦,阿根廷,澳大利亚,塞尔维亚,荷兰,尼日利亚、日本,美国,中国,新西 兰,巴西,比利时,韩国,喀麦隆,洪都拉斯,意大利

    import java.util.ArrayList; import java.util.List; import java.util.Random; public class List1 { pub ...

  8. 已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数

    #include<iostream> using namespace std; //#define maxn 2000010 #include<stdio.h> //int a ...

  9. 现有1~100 共一百个自然数,已随机放入一个有98个元素的数组a[98].要求写出一个尽量简单的方案找出没有被放入数组的那2个数,并在屏幕上打印这2个数

    void test7() { try { ]; ]; ]; ; ; int i; ; i < num.Length; i++) { num[i] = i + ; num1[i] = i + ;/ ...

随机推荐

  1. Timer TimerTask schedule scheduleAtFixedRate

    jdk 自带的 timer 框架是有缺陷的, 其功能简单,而且有时候它的api 不好理解. import java.util.Date; import java.util.Timer; import ...

  2. windows 配置java环境变量

    https://www.cnblogs.com/cnwutianhao/p/5487758.html

  3. stage的划分

    stage的划分是以shuffle操作作为边界的,遇到一个宽依赖就分一个stage 一个Job会被拆分为多组Task,每组任务被称为一个Stage就像Map Stage, Reduce Stage.S ...

  4. hive命令的执行方式

    1.通过cli直接执行 2.hive -e "hql" 如:[root@host ~]# hive -e "use gamedw;show tables" [r ...

  5. Mac安装Python3报错Permission denied @ dir_s_mkdir - /usr/local/Frameworks

    brew安装Python3时出现的问题: Error: Permission denied @ dir_s_mkdir - /usr/local/Frameworks /usr/local/Frame ...

  6. 关于 roadhog 2.0 版本之后不支持 cssModulesExclude

    cssModulesExclude 是用于 cssModules模块之后 ,解决不需要 cssModules 模块的样式文件, 了解 cssModules 看这里 https://segmentfau ...

  7. 深度学习原理与框架-卷积网络细节-经典网络架构 1.AlexNet 2.VGG

    1.AlexNet是2012年最早的第一代神经网络,整个神经网络的构架是8层的网络结构.网络刚开始使用11*11获得较大的感受野,随后使用5*5和3*3做特征的提取,最后使用3个全连接层做得分值得运算 ...

  8. 一个简单的SignalR例子

    本文介绍如何使用SignalR的Hub制作一个简单的点赞页面.不同浏览器(或者不同窗口)打开同一个页面,在任何一个页面点赞,所有页面同时更新点赞数. 1.使用Visual Studio Communi ...

  9. compose配置文件参数详解

    转自:https://www.cnblogs.com/jsonhc/p/7814138.html 本文介绍compose配置文件参数的使用,熟练编写compose文件 [root@docker lnm ...

  10. Linux命令:chmod

    https://baijiahao.baidu.com/s?id=1616750933810368135&wfr=spider&for=pc