趣题 一道面试题的解法:随机数生成
- 格式:pdf
- 大小:98.36 KB
- 文档页数:2
第1篇一、题目背景猜数字游戏是一款经典的编程练习题,旨在考察面试者对Java编程基础、面向对象设计、异常处理、算法和数据结构等方面的掌握程度。
本题目要求面试者使用Java编程语言实现一款猜数字游戏,游戏规则如下:1. 程序随机生成一个0-9之间的整数作为秘密数字。
2. 玩家有3次机会猜测这个数字。
3. 每次猜测后,程序会给出提示,告诉玩家猜的数字是大了、小了,还是猜对了。
4. 如果玩家在3次机会内猜对了数字,则游戏成功;否则,游戏失败。
5. 游戏结束后,询问玩家是否继续进行下一轮游戏。
二、面试要求1. 完整的Java代码实现,包括但不限于以下类和方法:- `GuessNumberGame`:游戏主类,负责游戏流程控制。
- `RandomNumberGenerator`:随机数生成器类,负责生成秘密数字。
- `Player`:玩家类,负责玩家的输入和输出。
- `GameResult`:游戏结果类,用于存储游戏胜利或失败的状态。
2. 代码结构清晰,遵循面向对象设计原则。
3. 使用控制语句(如if、for、while等)和异常处理(如try-catch)来控制程序流程和错误处理。
4. 程序运行过程中,能够友好地与用户进行交互,提供清晰的提示信息。
5. 具备良好的代码注释,解释关键代码逻辑。
三、面试题目1. 设计并实现`GuessNumberGame`类,包括以下方法:- `void startGame()`:开始新的一轮游戏。
- `void generateSecretNumber()`:生成秘密数字。
- `void checkGuess(int guess)`:检查玩家猜测的数字,并给出提示。
- `void showGameResult()`:显示游戏结果。
2. 设计并实现`RandomNumberGenerator`类,包括以下方法:- `int generateRandomNumber()`:生成0-9之间的随机整数。
最近做了一些Tencent及几家公司的面试题,发现有一种关于产生随机数的类型的题目。
看到多有大牛们做出来,而且效率很高,也有不知道怎么做的,最近根据几个产生随机数的题目整理一下,发现所有的类似题目可以用一种万能钥匙解决。
故分享,欢迎发表不同看法,欢迎吐槽。
题目一:给定能随机生成整数1到5的函数,写出能随机生成整数1到7的函数。
利用随机函数rand()函数生成一个等概率随机生成整数1到5的函数Rand5(),然后根据Rand5()生成Rand7(),代码如下:[cpp]view plaincopy1.#include <iostream>ing namespace std;3.int Rand5()4.{5.int n =1 + rand()%5;6.return n;7.}8.int Rand7()9.{10.int n ,tmp1 ,tmp2;11.do12. {13. tmp1 = Rand5();14. tmp2 = Rand5();15. n = (tmp1-1)*5+tmp2;//n是可以取1~25的随机的数。
16. } while (n>21);//当n>21舍去,这样n只能取1~21,对7取模就能取1~7之间的随机数17.18.return 1+n%7;19. }20.int main()21.{22.for (int i = 0 ; i < 100 ; i++)23. {24. cout<<Rand5()<<" ";25. }26. cout<<endl;27.for (int j = 0 ; j < 100 ; j++)28. {29. cout<<Rand7()<<" ";30. }31. cout<<endl;32.return 0;33.}生成结果如下:算法的关键就是两次运用Rand5(); tmp1 = Rand5();tmp2 = Rand5();n = (tmp1-1)*5+tmp2;n的最大值为25,为了满足产生的1到7等概率,所以n最大应该取7的倍数,所以当n>21时应舍去,为了测试是否概率真的相等,写一个测试函数:[cpp]view plaincopy1.int main()2.{3.const int Max = 10000000;4.int a[7] = {0};5.for (int ii = 0 ; ii < Max ; ++ii)6. {7.switch (Rand7())8. {9.case 1:a[0]++;break;10.case 2:a[1]++;break;11.case 3:a[2]++;break;12.case 4:a[3]++;break;13.case 5:a[4]++;break;14.case 6:a[5]++;break;15.case 7:a[6]++;break;16.default:cerr<<"Error!"<<endl;exit(-1);17. }18. }19.for (int r = 0 ; r<7 ; r++)20. {21. cout<< r+1<<":"<<setw(6)<<setiosflags(ios::fixed)<<setprecision(2)<<double(a[r])/Max*100<<"%"<<endl;22. }23.return 0;24.}题目二:已知rand7() 可以产生 1~7 的7个数(均匀概率),利用rand7() 产生rand10() 1~10(均匀概率)解法与上面类似,同样只用两个rand7()生成rand10()即可。
[典型例题探究]【例1】已知从n 个不同元素中取出m 个元素的方法数为 12)2()1()1()2()1(⋅⋅⋯⋅-⋅-⋅+-⋅⋯⋅-⋅-⋅m m m m n n n n ,在放有5个红球、4个黑球、3个白球的袋中,任意取出3个球,求取出的全是同色球的概率.分析:把球看作元素对待,综合利用古典概型和互斥事件概率公式. 解:从12个球中任取3个球的基本事件数即是从12个不同元素中取出3个元素的方法数,为123101112⨯⨯⨯⨯=220.规律发现古典概型是计算概率的基础,它常与互斥事件、对立事件等其他概率知识混合使用.记“取出的全是同色球”为事件A ,“取出的全是红色球”“取出的全是黑色球”“取出的全是白色球”分别是事件B 、C 、D . 由古典概型知P (B )=22010220123345=⨯⨯⨯⨯,P (C )=2204220123234=⨯⨯⨯⨯,P (D )=2201220123123=⨯⨯⨯⨯.∴P (A )=P (B ∪C ∪D )=P (B )+P (C )+P (D )=220422010+443220152201==+. 一个事件包含几种情况就是包含几个互斥事件,此题中每一个互斥事件又是古典概型,故应用古典概型概率公式.【例2】种植某种树苗,成活率为0.9,若种植这种树苗5棵,求恰好成活4棵的概率.分析:这里试验的可能结果(即基本事件)虽然很多但共有有限个,然而每个结果的出现不是等可能的,故不能应用古典概型概率公式,我们采用随机模拟的方法.对于满足“有限性”但不满足“等可能性”的概率问题我们可采取随机模拟方法.解:利用计算器或计算机产生0到9之间取整数值的随机数,我们用0代表不成活,1至9的数字代表成活,这样可以体现成活率是0.9.因为是种植5棵,所以每5个随机数作为一组,可产生30组随机数.根据成活率设计要产生的随机数的个数,并赋予它们相应的含义.69801 66097 77124 22961 74235 31516 29747 24945 57558 65258 74130 23224 37445 44344 33315 27120 21782 58555 61017 45241 44134 92201 70362 83005 94976 56173 34783 16624 30344 01117这就相当于做了30次试验,在这些数组中,如果恰有一个0,则表示恰有4棵成活,其有9组这样的数,于是我们得到种植5棵这样的树苗恰有4棵成活的概率为309=30%. 种植5棵树相当于作5次试验,故5个随机数作为一组,你体会到分组的方法了吗?。
(整数值)随机数(random numbers)的产生【知识梳理】1.随机数的产生(1)标号:把n个大小,形状相同的小球分别标上1,2,3,…,n;(2)搅拌:放入一个袋中,把它们充分搅拌;(3)摸取:从中摸出一个.这个球上的数就称为从1~n之间的随机整数,简称随机数.2.伪随机数的产生(1)规则:依照确定算法;(2)特点:具有周期性(周期很长);(3)性质:它们具有类似随机数的性质.计算机或计算器产生的随机数并不是真正的随机数,我们称为伪随机数.3.利用计算器产生随机数的操作方法用计算器的随机函数RANDI(a,b)或计算机的随机函数RANDBETWEEN(a,b)可以产生从整数a到整数b的取整数值的随机数.例如,用计算器产生1到25之间的取整数值的随机数,方法如下:4.利用计算机产生随机数的操作程序每个具有统计功能的软件都有随机函数,以Excel软件为例,打开Excel软件,执行下面的步骤:(1)选定A1格,键入“=RANDBETWEEN(0,1)”,按Enter键,则在此格中的数是随机产生的0或1。
(2)选定A1格,按Ctrl+C快捷键,然后选定要随机产生0,1的格,比如A2至A100,按Ctrl+V快捷键,则在A2至A100的数均为随机产生的0或1,这样相当于做了100次随机试验.(3)选定C1格,键入频数函数“=FREQUENCY(A1∶A100,0.5)",按Enter键,则此格中的数是统计A1至A100中,比0.5小的数的个数,即0出现的频数.(4)选定D1格,键入“=1-C1/100”,按Enter键,在此格中的数是这100次试验中出现1的频率.【常考题型】题型一、随机数的产生方法【例1】某校高一年级共有20个班1 200名学生,期末考试时,如何把学生随机地分配到40个考场中去?[解] 第一步,n=1;第二步,用RANDI(1,1 200)产生一个[1,1 200]内的整数随机数x表示学生的座号;第三步,执行第二步,再产生一个座号,若此座号与以前产生的座号重复,则执行第二步,否则n=n+1;第四步,如果n≤1 200,则重复执行第三步,否则执行第五步;第五步,按座号的大小排列,作为考号(不足四位的前面添上“0”,补足位数),程序结束.【类题通法】。
【转】趣题: 一道面试题的解法:随机数生成
原题:
Given a random number generator which can generate the number in range (1,5) uniformly. How can you use it to build a random number generator which can generate the number in range (1,7) uniformly?
译文:
给定一个随机数生成器,这个生成器能均匀生成1到5(1,5)的随机数,如何使用这个生成器生成均匀分布的1到7(1,7)的数?
用(1,5) 生成器去扩展它的生成数范围,一次不行,我两次呢?没错,我们先后取两次,然后把结果相乘,那么可以知道,这两个数相乘后的范围是1~25。
并且取到1~25 中间的任何一个数的可能性是相同的。
21是7的3倍,于是我们就有了这样的映射:
1~3 –> 1
4~6 -> 2
…
19~21->7
如果得到的数大于21,则重取。
这样做,我们至少可以保证,生成的1~7的数的概率是相同的,因此满足题目的要求。
算法二:
二进制,由于7的二进制是111
1-2映射到0,3跳过,4-5映射到1
生成三位的二进制即可
-----------------------------------------------随机数范围扩展方法总结【转】问题描述
已知random3()这个随机数产生器生成[1, 3]范围的随机数,请用random3()构造random5()函数,生成[1, 5]的随机数?
问题分析
如何从[1-3]范围的数构造更大范围的数呢?同时满足这个更大范围的数出现概率是相同的,可以想到的运算包括两种:加法和乘法
考虑下面的表达式:
3 * (random3() –1) + random3();
可以计算得到上述表达式的范围是[1, 9] 而且数的出现概率是相同的,即1/9
下面考虑如何从[1, 9]范围的数生成[1, 5]的数呢?
可以想到的方法就是rejection sampling 方法,即生成[1, 9]的随机数,如果数的范围不在[1, 5]内,则重新取样
解决方法CPP CODEint random5(){int val =0;do{ val =3*(random3()-1)+
random3();}while(val >5);return val;}归纳总结
将这个问题进一步抽象,已知random_m()随机数生成器的范围是[1, m] 求random_n()生成[1, n]范围的函数,m < n && n <= m *m
一般解法:
CPP CODEint random_n(){int val =0;int t;// t为n最大倍数,且满足t <= m * mdo{ val = m *(random_m()-1)+ random_m();}while(val > t);return val;}。