一、从5随机到7及其扩展

  题目1:给定一个等概率随机产生1~5的随机函数rand1to5:

    public int rand1To5() {
return (int)(Math.random() * 5) + 1;
}

  除此之外,不能使用任何额外的随机机制,请用rand1To5实现等概率随机产生1~7的随机函数random1To7。

  解法:

  第一步:rand1To5()等概率随机产生1,2,3,4,5

  第二步:rand1To5()-1等概率随机产生0,1,2,3,4

  第三步:(rand1To5()-1)*5等概率随机产生0,5,10,15,20

  第四步:(rand1To5()-1)*5 + rand1To5()-1等概率随机产生0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24

  第五步:如果第四步产生的结果大于20,则重复进行第四步,直到产生的结果在0~20之间,同时可以知道出现21~24的概率,会平均分配到0~20上。

  第六步:第五步会等概率随机产生0~20,所以第五步的结果进行%7操作,就会等概率产生0~6

  第七步:将第六步的结果再加1,就会等概率随机产生1~7

    public int rand1To6() {
int num = 0;
do {
num = (rand1To5() - 1) * 5 + rand1To5() - 1;
} while (num > 20);
return num % 7 + 1;
}

  

  题目2:给定一个以p概率产生0,以1-p概率产生1的随机函数random01p:

    public int rand01p() {
double p = 0.83;
return Math.random() < p ? 0 : 1;
}

  除此之外,不能使用任何额外的随机机制,请用rand01p实现等概率随机产生1~6的随机函数random1To6。

  分析:

    不断重复执行rand01p()函数,直到第一次之后出现的数与第一次出现的数不同为止。

    rand01p()第一次产生的数为0的概率为p(1-p),rand01p第一次产生的数为1的概率为(1-p)p,则说明可以使用rand01()方法等概率产生0和1

    public int rand01() {
int num;
do {
num = rand01p();
} while (num == rand01p());
return num;
}

  解法:

    第一步:rand01()等概率随机产生0和1

    第二步:rand01()*2等概率随机产生0和2

    第三步:rand01()*2+rand01()等概率随机产生0,1,2,3,即生成rand0To3()方法

    public int rand0To3() {
return rand01() * 2 + rand01();
}

    第四步:rand0To3()*4+rand0To3()等概率随机产生0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15

    第五步:如果第四步产生的结果大于11,则重复进行第四步,直到产生的结果在0~11之间,那么12~15的概率就会平均分配到0~11上

    第六步:对第五步的结果进行%6操作,就会等概率随机产生0~5,然后再对这个结果加1,就会等概率随机产生1~6

    public int rand1To6ByRand0To3() {
int num = 0;
do {
num = rand0To3() * 4 + rand0To3();
} while (num > 11);
return num % 6 + 1;
}

  题目3:给定一个等概率随机产生1~M的随机函数rand1ToM:

    public int rand1ToM(int m) {
return (int)(Math.random() * m) + 1;
}

  除此之外,不能使用任何额外的随机机制,有两个输入参数,分别为m和n,请用rand1ToM(m)实现等概率随机产生1~n的随机函数rand1ToN。

  分析:

    总结题目1和题目2的解法

    如果要产生1~7,那么考虑随机生成0~6,因此等概率产生0~24(插空),然后等概率产生0~20(筛),进行%7操作,结果加1

    如果要产生1~6,那么考虑随机生成0~5,因此等概率产生0~15(插空),然后等概率产生0~11(筛),进行%6操作,结果加1

    针对题目3,可以有,如果M≥N,直接进入筛过程;如果M<N,先进入插空过程,直到产生比N大的随机范围后,再进入筛过程。

  解法:

    调用k次rand1ToM(m),生成有k为的M进制数,并且产生的范围要大于或等于N。例如,题目1中由随机5到随机7,首先生成0~24范围内的数,也就是0~(5²-1),在把范围扩到大于或等于N的级别之后,如果真实生成的数大于或等于N,就忽略,只留下小于或等于N的数,那么在0~N-1上就可以做到均匀分布。

    以m=5,n=7即由随机5产生随机7为例:

    第一步:将10进制的n-1转换成m进制数,即将7-1=6转换成5进制数,也就是11

    // 将10进制的value转换成m进制数
public int[] getMSysNum(int value, int m) {
int[] res = new int[32];
int index = res.length - 1;
while (value != 0) {
res[index--] = value % m;
value /= m;
}
return res;
}

    第二步,等概率产生一个0~6的随机数,用5进制表示,也就是0~11的随机数,例如随机数6用10表示

    // 等概率随机产生一个0~nMSys范围的数,只不过是用m进制表达的
public int[] getRanMSysNumLessN(int[] nMSys, int m) {
int[] res = new int[nMSys.length];
int start = 0;
while (nMSys[start] == 0) {
start ++;
}
int index = start;
boolean lastEqual = true;
while (index != nMSys.length) {
res[index] = rand1ToM(m) - 1;
if (lastEqual) {
if (res[index] > nMSys[index]) {
index = start;
lastEqual = true;
continue;
} else {
lastEqual = res[index] == nMSys[index];
}
}
index++;
}
return res;
}

    第三步:将第二步产生的0~6范围内的5进制数转换成十进制输出:将10转换成6输出

    // 把m进制数转成十进制数
public int getNumFromMSysNum(int[] mSysNum, int m) {
int res = 0;
for (int i = 0; i < mSysNum.length; i++) {
res = res * m + mSysNum[i];
}
return res;
}

  总方法rand1ToN:

    public int rand1ToN(int n, int m) {
int[] nMSys = getMSysNum(n - 1, m);
int[] randNum = getRanMSysNumLessN(nMSys, m);
return getNumFromMSysNum(randNum, m) + 1;
}

  

  二、一行代码求两个数的最大公约数

  题目:给定两个不等于0和整数M和N,求M和N的最大公约数

  解法:根据欧几里得算法(又叫辗转相除法),如果q和r分别是m除以n的商及余数,即m=nq+r,那么m和n的最大公约数等于n和r的最大公约数。

    public int gcd(int m, int n) {
return n == 0 ? m : gcd(n, m % n);
}

  三、判断一个点是否在矩形内部

  四、判断一个点是否在三角形内部

  五、折纸问题

  六、设计有setAll功能的哈希表

  七、设计可以变更的缓存结构

  八、设计RandomPool结构

  九、调整[0,x)上数出现的概率

  十、整数数组的最小不可组成和

  十一、从N个数中等等概率带你M个数

  十二、判断一个数是否为回文数

  十三、在有序旋转数组中找到最小值

  十四、在有序旋转数组中找到一个数

  十五、一种消息接收并打印的结构设计

  十六、在两个长度相等的排序数组中找到上中位数

  十七、两个有序数组间相加和Top K问题

  十八、蓄水池算法

  

  

OptimalSolution(9)--其他问题(1)的更多相关文章

  1. OptimalSolution(9)--其他问题(2)

    一.有关阶乘的两个问题 二.最大的leftMax与rightMax之差的绝对值 三.路径数组变为统计数组 四.一种字符串和数字的对应关系 五.1到n中1出现的次数 六.数字的英文表达和中文表达 七.分 ...

  2. OptimalSolution(8)--位运算

    一.不用额外变量交换两个整数的值 如果给定整数a和b,用以下三行代码即可交换a和b的值.a = a ^ b; b = a ^ b; a = a ^ b; a = a ^ b :假设a异或b的结果记为c ...

  3. OptimalSolution(7)--大数据和空间限制

    一.布隆过滤器 问题:不安全网页的黑名单包含100亿个黑名单网页,每个网页的URL最多占用64B.现在想要实现一种网页过滤系统,可以根据网页的URL判断该网页是否在黑名单上,如何设计该系统. 要求:允 ...

  4. OptimalSolution(6)--栈和队列

    一.设计一个有getMin功能的栈 题目:实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作.pop.push.getMin操作的时间复杂度都是O(1). 思路:设计两个栈,一 ...

  5. OptimalSolution(5)--数组和矩阵问题(2)2

    一.找到无序数组中最小的k个数 二.在数组中找到出现次数大于N/K的数 三.最长的可整合子数组的长度 四.不重复打印排序数组中相加和为给定值的所有二元组和三元组 五.未排序正数数组中累加和为给定值的最 ...

  6. OptimalSolution(5)--数组和矩阵问题(1)简单

    一.转圈打印矩阵 题目:给定一个整型矩阵matrix,按照转圈的方式打印它. 要求:额外空间复杂度为O(1) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 打印结果为: ...

  7. OptimalSolution(4)--字符串问题(2)进阶

    一.将整数字符串转成整数值 二.判断字符数组中是否所有的字符都只出现过一次 三.在有序但含有空的数组中查找字符串 四.数组中两个字符串的最小距离 五.添加最少字符使字符串整体都是回文字符串 六.括号字 ...

  8. OptimalSolution(4)--字符串问题(1)简单

    一.判断两个字符串是否互为变形词 问题:给定两个字符串str1和str2,如果str1和str2中出现的字符种类一样且每种字符出现的次数也一样,那么str1与str2互为变形词. 举例:str1=“1 ...

  9. OptimalSolution(3)--链表问题(2)进阶

    一.环形单链表的约瑟夫问题 二.判断一个链表是否为回文结构 三.将单向链表按某只划分成左边小.中间相等.右边大的形式 四.复制含有随机指针节点的链表 五.两个单链表相交的一系列问题 六.将单链表的每K ...

随机推荐

  1. vue知识点整理

    1.对于mvvm的理解 mvvm是model-view-viewModel vue是以数据为驱动的,vue自身将dom和数据进行绑定,一旦创建绑定,dom和数据将保持同步,每当数据发生变化,dom也会 ...

  2. Dubbo学习系列之九(Shiro+JWT权限管理)

    村长让小王给村里各系统来一套SSO方案做整合,隔壁的陈家村流行使用Session+认证中心方法,但小王想尝试点新鲜的,于是想到了JWT方案,那JWT是啥呢?JavaWebToken简称JWT,就是一个 ...

  3. linux服务器创建虚拟路径解决文件上传路径隔离问题

    需求环境 图片上传最简单的就是上传web项目下,这样图片与项目不可分离会产生很多不必要的影响.例如:重新部署项目需要把所有上传的图片再copy一份等. 图片与项目分离有好几种方式: 方式一.在linu ...

  4. Flask基础(17)-->防止 CSRF 攻击

    CSRF CSRF全拼为Cross Site Request Forgery,译为跨站请求伪造. CSRF指攻击者盗用了你的身份,以你的名义发送恶意请求. 包括:以你名义发送邮件,发消息,盗取你的账号 ...

  5. 在创建activiti5..22所需的25张表时 ,所用的方法和遇到的问题。

    最近在学习关于activiti流程设计的相关内容,首先第一步就需要了解25张activiti相关的表,具体的每张表的含义 请自行百度. 这里讲一下 用java代码生成所需要的25张表,很简单: pub ...

  6. ['1', '2', '3'].map(parseInt) what & why ?

    这是今天在 Advanced-Frontend组织 看到一个比较有意思的题目.主要是讲JS的映射与解析早在 2013年, 加里·伯恩哈德就在微博上发布了以下代码段: ['10','10','10',' ...

  7. Eclipse的Debug(一)

    本文链接:https://blog.csdn.net/u011781521/article/details/55000066    http://blog.csdn.net/u010075335/ar ...

  8. 安装sublime插件安装不上遇到的各种坑

    为了学习VUE , 发现没有高亮代码, 百度原来需要安装插件,安装过程中遇到了各种坑,记录下来避免大家踩坑, 首先用代码安装快捷键  ctrl+`   粘贴代码 import urllib.reque ...

  9. ORM查询总结版

    目录 概要 ORM常用字段 ORM基础 自定义一个插入类型,即固定长度 创建类终极版 多对多关系表创建 常用几个代码 参数 ORM与数据库代码对应的关系 外键使用分表很麻烦,要先删除主表后,再删除 不 ...

  10. python编程基础之三十一

    面向对象:一开始接触面向对象其实感觉不好用,但是对于一些复杂的问题,使用面向对象其实更加容易,逻辑不容易混乱 它的核心是:类 和 对象 类:对一系列事物的抽象概念,可以视为一张图纸, 对象:就是对类这 ...