当前位置: 首页 > 科技观察

【LeetCode】等概率题,我有妙招!

时间:2023-03-18 18:01:42 科技观察

在解决算法问题的时候,我们经常会遇到需要等概率的问题。以leetcode470.使用Rand7()实现Rand10()为例。现有方法rand7可以生成1到7范围内的均匀随机整数,尝试写一个方法rand10生成1到10范围内的均匀随机整数。??不讨论最优解,只讨论算法思想。看到等概率的问题,首先想到的肯定是转化成二进制来处理。思路是把等概率转化为等概率出现0和1,然后从0和1开始,增加位数来处理其他等概率的数字。拆解上面的题目,我们用Rand7转换成Rand2。让Rand2的返回结果均等地出现0和1,我们就可以用4位二进制数生成包含0-15的数。舍去10到15,保留0到9,结果加1得到一个1到10的随机数。第一步转换二元函数Rand7()的结果就是1,2,3,4,5、6出现的概率相等。拆解后,1、2、3和4、5、6等概率出现。当1,2,6出现时,3返回0,出现4,5,6时返回1Declarefunctionrand7():numberfunctionRand2():number{returnRand7()>3?1:0}现在我们有了转换函数Rand2,然后我们使用随机生成4位二进制数,那么我会得到一个函数functionRand15():number{returnRand2()*2*2*2+Rand2()*2*2+Rand2()*2+Rand2()}即平均生成0到15上面的代码有点笨,我们用shift的方式优化,左移运算符是二进制进位。functionRand15():number{return(rand2()<<3)+(rand2()<<2)+(rand2()<<1)+(rand2()<<0)}最后的Rand10()函数,我们只需要丢弃10~15个。functionRand10():number{letnum:number//如果小于10则使用dowhile循环返回结束循环的结果,继续rolldo{num=Rand15()}while(num>9)returnnum+1//别忘了+1}这道题解决了,再来一道题,思路也是用二元等概率。给定一个随机函数f,它以P概率返回0,以1-P概率返回1。这是您可以使用的唯一随机机制。如何等概率返回0和1?1为P的概率为1-P00的概率为P*P11的概率为(1-P)*(1-P)01的概率为P*(1-P)的概率10的是(1-P)*P并且这两个是相等的(汇率),那么我们只需要保留01和10,舍弃00和11就可以得到等概率的P*(1-P)10和01这些两个数不想相等就声明functionf():0|1functionround01():number{letnum:numberdo{num=f()}while(num==f())returnnum}总结一下,两个小问题是用二进制位解决的算法问题。解决问题也有两个大方向。一种是将高基数拆成等概率的二进制,然后组成目标数。另一种是通过提升构造等概率。