题目链接

https://leetcode-cn.com/problems/implement-rand10-using-rand7/

题意:

给定一个rand7()的生成器,求解如何产生一个rand10()的生成器。注意这里定义rand7()的范围是17,而不是06

思路:

关键在于产生的结果必须是等概率的,这是一类非常泛化的题。具体而言涉及到由任意的randm()转化到randn()的计算方式。

详细解读可以参考:https://blog.csdn.net/u010025211/article/details/49668017

在这里我们假设m>n,比如由rand7()转化到rand3()

那么我们只需要把大于3的倍数的值先舍去,比如

int rand3() {
int x=INT_MAX;
while(x>6){
x=rand7();
}
return x%3+1;
}

分析一下产生1~6的概率,那么1/7+1/7*1/7+(1/7)2*1/7+...+(1/7)n*1/7=1/6

而从1~6一共产生的数为1,2,3,4,5,6每个数字出现的概率相同,所以利用x%3+1可以转化得到1,2,3的出现概率也相同

考虑一般化的情况,如果m>n那么randm转化为randn的方式可以理解为:

int rand_n(){
//m>n
int d=m/n;
int ans=INT_MAX;
while(ans>n*d){//最靠近m的整数
ans=rand_m();
} return ans%n+1;
}

同理如果m<n时,比如rand7()转移到rand10(),这时候需要等距离覆盖,比如如果直接用两个rand7()相加得到[2,14]之间所有数字的和,但是显然这个区间每个数字出现的次数的概率不是相同的(两边出现的概率小,中间出现的概率大),那么怎么才能生成等概率,却又能覆盖掉10以类的所有数字呢?

这里采用一种映射:7*(rand7()-1)+rand7(),前面rand7()-1映射到[0,6],每个数字等概率,7*(rand7()-1)映射到[0,7,14,21,28,35,42],每个数字等概率,后面映射到[1,2,3,4,5,6,7]每个数字等概率,那么两者得到的和[1,2,3,4,5,6,7,8,9,...,42]之间出现的每个数字都是等概率的,即:rand42()=7*(rand7()-1)+rand7()

然后再从rand42()映射回来rand10()就可以了

class Solution {
public:
int randn() {
int x=INT_MAX;
// while(x>10){ //这里还可以再优化
while(x>40){
x=7*(rand7()-1)+rand7();//rand42()
// if(x<=10){
// brmeak;
// }
}
return x%10+1;
}
};

同理可以推出更普遍的情况,如果m<n,那么由rand_m()映射到rand_n()可以为:

int rand_n(){
//m<n
//假设m^k>=n && m^(k-1)<n
int k=0;
int mul=0;
while(m<n){
mul*=m;
k++;
} int ans=INT_MAX;
while(ans>(mul/n)*n){
int tmp=rand_m();
for(int i=1;i<=k;i++){
tmp=m*(tmp-1)+rand_m(); //rand2*m
}
ans=tmp;
} return ans%n+1;
}

leetcode 470. 用 Rand7() 实现 Rand10() (数学,优化策略)的更多相关文章

  1. Java实现 LeetCode 470 用 Rand7() 实现 Rand10()

    470. 用 Rand7() 实现 Rand10() 已有方法 rand7 可生成 1 到 7 范围内的均匀随机整数,试写一个方法 rand10 生成 1 到 10 范围内的均匀随机整数. 不要使用系 ...

  2. LeetCode 470. 用 Rand7() 实现 Rand10()(Implement Rand10() Using Rand7())

    题目描述 已有方法 rand7 可生成 1 到 7 范围内的均匀随机整数,试写一个方法 rand10 生成 1 到 10 范围内的均匀随机整数. 不要使用系统的 Math.random() 方法. 示 ...

  3. 470. 用 Rand7() 实现 Rand10()

    已有方法 rand7 可生成 1 到 7 范围内的均匀随机整数,试写一个方法 rand10 生成 1 到 10 范围内的均匀随机整数. public class Solution { public s ...

  4. 随机数范围扩展(如rand7()到rand10())(转)

    题目:已知有个rand7()的函数,返回1到7随机自然数,让利用这个rand7()构造rand10() 随机1~10.分析:要保证rand10()在整数1-10的均匀分布,可以构造一个1-10*n的均 ...

  5. rand7生成rand10,rand1生成rand6,rand2生成rand5(包含了rand2生成rand3)

    这种题要分两步,第一步是“插空儿”,第二步是“筛” 1.rand7生成rand10 只要是10的倍数就好 int rand10() { int num; do{ num = (rand7() - ) ...

  6. 利用rand7()构造rand10()

    题意 已知有个rand7()的函数,返回1到7随机自然数,让利用这个rand7()构造rand10() 随机1~10 参考代码 int rand7() { srand((int)time(NULL)) ...

  7. 利用rand7() 产生rand10()(腾讯)

    题目1:已知rand7() 可以产生 1~7 的7个数(均匀概率),利用rand7()  产生rand10()   1~10(均匀概率) int rand10() { int temp; int te ...

  8. 图解Leetcode组合总和系列——回溯(剪枝优化)+动态规划

    Leetcode组合总和系列--回溯(剪枝优化)+动态规划 组合总和 I 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 ...

  9. mysql索引之四:复合索引之最左前缀原理,索引选择性,索引优化策略之前缀索引

    高效使用索引的首要条件是知道什么样的查询会使用到索引,这个问题和B+Tree中的“最左前缀原理”有关,下面通过例子说明最左前缀原理. 一.最左前缀索引 这里先说一下联合索引的概念.MySQL中的索引可 ...

随机推荐

  1. 如何将 Dapper 换成 SqlSuagr ORM

    为什么要写这篇文章 因数我看到很多人虽然用着SqlSugar,但是同时也用着Dapper,因为SqlSugar兼容了Dapper所有API,所以既然你用了SqlSugar那么就没有必要在同一个项目中使 ...

  2. 接口测试工具 Jmeter使用笔记(一:编写一个http请求)

    记录学习过程 一.安装Jmeter 1.JAVA环境 JDK下载地址http://java.sun.com/javase/downloads/index.jsp 配置系统变量: (1)JAVA_HOM ...

  3. LLVM程序分析日记之插桩BranchInst

    1. splitblockandinsertifthenelse() 一个代码例子:StackOverflow 2. SplitBlockAndInsertIfThen() 或者仅仅想插桩if the ...

  4. webpack入门级 - 从0开始搭建单页项目配置

    前言 webpack 作为前端最知名的打包工具,能够把散落的模块打包成一个完整的应用,大多数的知名框架 cli 都是基于 webpack 来编写.这些 cli 为使用者预设好各种处理配置,使用多了就会 ...

  5. PHP面向对象的学习(封装,继承,多态)

    这个文章就是记录  巩固一下PHP的面向对象的部分 ,无非就是封装,继承,多态等等这几部分 这里参考了一位大佬总结的文章:https://www.cnblogs.com/adaia/p/6986576 ...

  6. MyBatis史上最全文章

    老规矩,本篇文章 不做 MyBatis 的 编码讲解 ,只介绍 文章学习的一些优秀文章 重点在于不要循规蹈矩,教程 这样走,你不一定要按他这样走,按自己的方式来,学习效率会更高,网上的教程有很多,今天 ...

  7. Docker实例开机启动

    部署项目服务器时,为了应对停电等情况影响正常web项目的访问,会把Docker容器设置为开机自动启动. 在使用docker run启动容器时,使用--restart参数来设置: docker run ...

  8. device_create为何可以在/sys/class/具体类/属性文件?怎么实现的

    答案: 版本3.6.9: device_create -> device_register -> device_add -> device_add_attrs -> devic ...

  9. Java学习日报7.29

    package student;import java.util.*;public class student { Scanner sc=new Scanner(System.in); private ...

  10. Spring IOC 笔记

    什么是IOC与DI IOC(inversion of control) 它描述的其实是一种面向对象编程中的设计原则,用来降低代码之间的耦合度, 而DI(dependency Injection)依赖注 ...