美团 生成器问题

这篇博客回顾了美团面试中关于随机数生成器的问题,包括如何设计生成器使得生成1、2、3的概率分别为0.5、0.3、0.2。作者通过组合现有随机生成器的输出来构造新的生成器,如利用二进制、七进制的转换,以及通过三进制组合来实现目标概率分布。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

可能是没吃饭就去面试了,一塌糊涂,好尴尬,生成器竟然卡壳了···,问的随机数生成器生成1、2、3的概率相等,都为1/3,问如何设计生成器,使得生成1、2、3的概率为0.5、0.3、0.2.

先整体总结一下之前的生成器的问题

1给定一个随机生成器fun(),生成0和1的概率分别为0.5,那么如何构造一个生成0和1的概率分别是0.3和0.7的随机生成器?

可以考虑将其生成的数字0,1进行组合

int fun2()
{
	int n=0;
	int n1=fun();
	int n2=fun();
	int n3=fun();
	int n4=fun();
	n|=n1;
	n|=n2<<1;
	n|=n3<<2;
	n|=n4<<3;
	if(n<=2)
		return 0;
	else if(n<10)
		return 1;
	else
		return fun2();
}

2随机生成器生成0和1的概率分别为p和1-p,那么如何构造生成0和1为等概率的随机生成器?

同样都是是对0、1进行组合,生成00概率为p^2,生成01概率为p(1-p),生成10概率为(1-p)p,生成11概率为(1-p)^2,我们可以发现生成01和生成10概率是一样的,因此可以考虑使用这个作为生成0,1的等概率随机生成器。

int fun2()
{
	int n=0;
	int n1=fun();
	int n2=fun();
	n|=n1;
	n|=n2<<1;

	if(n==1)
		return 0;
	else if(n==2)
		return 1;
	else
		return fun2();
}

3描述RANDOM(a,b)的过程的一种实现,它只调用RANDOM(0,1)。
注:RANDOM(0,1)以等概率输出0或者1,
要求RANDOM(a,b)以等概率输出[a,b]之间的数(整数)
解决方案:
1,取 n=b-a+1,取最小的正整数m,使得 2^m >= n
2,调用RANDOM(0,1),输出m-bit位整数N ( N >= 0 and N <= 2^m-1)
3, if N >=0 and N <= b-a
then return a+N
else 重新执行步骤 2

4随机生成器生成0和1的概率分别为p和1-p,构造一个发生器,使得它构造1、2、3、…n的概率均为1/n,要求复杂度最低。

可以想怎么生成一个序列,里面有n个独立事件,概率是相等。而且我们能够猜测到这些概率的形式为 p^x*(1-p)^y,只有当x= y时,输出的概率相等的事件才最多,我们想要复杂度最低,所以最小的序列长度要求满足 C(2x,x) >=n ,我们只需要知道x就能够知道序列要多长了。

5已知有个rand7()的函数,返回1到7随机自然数,让利用这个rand7()构造rand10() 随机1~10。(其实和第一题一样一样的,第一题是二进制,这个是七进制)

如果能够得到一组等概率的数,不管是什么数,只要等概率而且个数大于10,那么问题就可以解决了。

发现(rand7()-1)*7+rand7() - 1,可以等概率的生成0到48。

呵呵,这不就得了,只要把10-48砍掉就可以了。不过这样的效率比较低。可以映射


接下来再看美团这道题,完全也可以用组合的方式,可以摇两次组合成三进制的两位

这样就有 (fun()-1) * 9 + (fun()-1) * 3 + fun() - 1  得到0~26等概事件 ,取前十个按概率分即可啦!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值