leetcode 用 Rand7() 实现 Rand10()

题目链接
思路一:拒绝采样
分析:
rand7() 1~7 每个概率都是 1/7
如果我们使用两次然后相乘,将会得到下图结果。
leetcode 用 Rand7() 实现 Rand10()_第1张图片

很明显,这里的数字1~49并不是每个都是概率一样的。
概率是如下这样的。
leetcode 用 Rand7() 实现 Rand10()_第2张图片
到这里,可以很简单的结束,挑选出10个概率相等的,然后建立和1~10的对应关系,即可。
但是这样有个缺点,这样可能调用很多次rand7(),因为你选了10个数,这里一共是25个数,也就是说,丢弃了15个数,很有可能长时间选出来的都是另外15个丢弃的。

其实我们只需要调整一下数字即可,也就是说,调用两次,然数字依次出来,也就是 1~49,每个数都可能被挑选出来,
{1~7}+{0 ~ 6} * 7这样就可以做到 1,2,3,4,5,6,7,8,9,10,11,12,14,,,,,,49都出来。

leetcode 用 Rand7() 实现 Rand10()_第3张图片
上面一行是rand7()出来的可能
下面一行是(rand7()-1) * 7 出来的可能

再按个加起来,正好就是1~49每个数都出来了。那么我们需要实现rand10(),那么我们可以丢弃后面的9个数字,也就是选择1 ~ 40,每个数字都是 4/49的概率,这样就是在49个数字中丢了9个数字,这样就可以降低调用rand7()的概率了。
代码:

class Solution extends SolBase {
    public int rand10() {
        int row, col, idx;
        do {
        	//第一次挑选
            row = rand7();
           	//第二次挑选
            col = rand7();
            //加起来    1~49
            idx = col + (row - 1) * 7;
        } while (idx > 40);//丢弃掉后面的9个数字
        //此时idx为   1~40    余10的话,就是  0 ~ 9 ,但是题目是要 1~10 所以加1
        return 1 + (idx - 1) % 10;
    }
}

方案二:独立事件+古典概率
首先看一个公式:P(AB) = P(A) * P(B)
解释一下,P(AB)是事件A和事件B同时发生的概率
P(A)是事件A发生的概率。P(B)同理。
这里要通过rand7()构造出来rand10(),那么我们可以,从rand7()中弄出两个事件,并且P(AB)的概率要是1/10即可。
那么我们可以这样,通过 0.2 * 0.5= 0.1 挑选两次。
第一次:1~6中的奇和偶数是一样多,所以可以看成奇数和偶数是一样的,也就是0.5,那么7就可以丢弃。
第二次:我们可以挑选1~5,[6,7]丢弃,那么1 ~5的每个数字的概率都是0.2。
然后再和1~10每个数对应起来就可以了。
代码:

class Solution extends SolBase {
    public int rand10() {
    	//分别表示第一次和第二次挑选出来的数字
        int firstTime, secondTime;
        //第一次挑选出来的数字不能大于6
        while ((firstTime= rand7()) > 6);
        //第二次挑选出来的数字不能大于5
        while ((secondTime= rand7()) > 5);
		
		// 如果是奇数
		if( (firstTime&1) == 1){
			//1~5
			return secondTime;
		}else{
		//如果是偶数
			// 6~10
			return secondTime + 5;
		}
    }
}

好好学习。
不打扰是我的温柔。

你可能感兴趣的:(算法,leetcode,算法,职场和发展)