470. 用 Rand7() 实现 Rand10()
-
题目
已有方法 rand7 可生成 1 到 7 范围内的均匀随机整数,试写一个方法 rand10 生成 1 到 10 范围内的均匀随机整数。
不要使用系统的 Math.random() 方法。
示例 1:
题目给的示例有些问题,因为给的函数是没有输入的,所以调用函数后直接生成均匀1到10的均匀随机整数即可。
-
难度:中等
-
分类:多看
-
题解
题解中给出的最多的方法也是比较简单能够想到的方法就是这个方法:题目要求尽量少调用rand7(),那么我们考虑就调用两次的情况会生成如下矩阵:
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 \ \ \ \ \ \ \ 也就是我们生成两个随机的rand7,然后将他们相乘,落入 [ 1 , 40 ] [1,40] [1,40]范围内的数,我们则需要,在范围外的数我们则舍去,然后再生成一次。对于范围内的数,我们则通过取余数操作使其落在 [ 1 , 10 ] [1,10] [1,10]范围内返回即可,该方法其实不止能生成rand10。代码如下:
class Solution extends SolBase { public int rand10() { int row=0; int col=0; int val=0; do{ row=rand7(); col=rand7(); val=col+(row-1)*7; } while(val>40); return (val)%10+1; } }
那么按照以上方式提交的结果则是:
通过以上结果我们能够得知效果还行,但是如果生成的数一直大于40,那么会一直进入循环状态中,会大大增加时间复杂度,直到无穷,所以这个方法有效但是还是存在着弊端。
-
优化
优化的方法也是不断生成rand7的随机数,但是不是直接生成两个rand7随机数,而是一次次递进生成。在上面的方法中我们先生成了两个rand7随机数,其范围为[1:49],然后我们舍去了[41,49],9个数,我们也可以进一步表示为[1:9],然后我们再调用一次rand7,与前面9个数组成的范围就达到了[1:63],那么我们又会舍弃[61:63]–>[1:3]3个数,我们再调用一次rand7,生成范围达到[1:21],我们再舍弃[21:21],这个时候我们再从头开始生成两个rand7即可,那么具体代码如下:
public int rand10() { int val; while(true) { int col=rand7(); int row=rand7(); val=col+(row-1)*7; if(val<41) { break; } col=val-40; row=rand7(); val=col+(row-1)*9; if(val<61) { break; } col=val-60; row=rand7(); val=col+(row-1)*2; if(val<21) { break; } } return val%10+1; }
那么取得的结果为:
我相信大家不但对题解感兴趣,同时对LeetCode如何进行测试这个算法也很感兴趣!我也是。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/implement-rand10-using-rand7
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。