面试题:给定一个函数rand()能产生1到m之间的等概率随机数,产生1到n之间等概率的随机数?
虽然TX的面试已经过去好几天了,然而惨痛的过程还历历在目。人生中第一次正式job面试就这么挂掉了。在于面试官的交流过程中,被问及了几个算法设计题,在今后几篇博文中,我一一总结与诸君分享。
1. 给定一个函数rand()能产生1到m之间的等概率随机数,产生1到n之间等概率的随机数? (为了简化问题,此处m小于n)
当被问到这个问题的时候,LZ我首先的想法就是能不能通过一次Rand就可以把结果找到。然后这个想法就被瞬间推翻了。
那么能否通过多次选取,然后组合呢? 答案是肯定的,然而悲剧的是,当时LZ的脑袋有点混乱了,想到了几个思路都不完备。
这几天冷静下来之后,仔细想了想,现给出一个可行的方案,跟大家讨论讨论。
假设:
已知函数 RandM能够生成[1,m]之间的随机数,满足均匀分布
Rand_mn 在已有RandM的基础上,生成均匀分布的[1,n]之间随机数的函数
m: 已知随机数最大值
n: 目标随机数最大值
PS : 此处约定 m<n && n< m*m
-----------------------------------------
思路:
(1) 通过分别两次生成[1,m]之间的均匀分布的随机数x,y那么 x,y 都属于[1,m],如果要将x和y进行组合的话
其最小覆盖问题变成了
z = a*x +y min a 使得z的取值均匀分布 s.t. x属于[1,m] y属于[1,m] |
(2) 由于 x,y 都是在[1,m]之前取值, 所以a能取的最小值为m。
(3) 当a=m时,z的取值范围为 [m+1, m*(m+1)]
若z=z-m, 则z的取值范围就变成了 [1, m*m],并且是均匀分布
(4) 此时,我们的问题就简化成了将[1,m*m]区间的值映射到[1,n]
(5) 采用“舍去法”, 令 re = m*m mod n,可知多余元素的个数
当z的值为(m*m-re, m*m]时,递归进行新的随机数生成,否则进行步骤6
(6) 将[1, m*m -re] 均匀分成n份, 每份的间隔为 gap = (m*m -re)/n;
C++代码实现如下:
#include <iostream>
#include <cmath>
#include <ctime>
using namespace std; int RandM(int m)
{
return rand()%m +;
} /********************************************
* Rand_mn 在已有RandM的基础上,
* 生成均匀分布的[1,n]之间随机数的函数
* m: 已知随机数最大值
* n: 目标随机数最大值
*
* PS : 此处约定 m<n && n< m*m
* -----------------------------------------
* 思路:
* (1) 通过分别两次生成[1,m]之间的均匀分布的随机数x,y
* 那么 x,y 都属于[1,m],如果要将x和y进行组合的话
* 其最小覆盖问题变成了
z = a*x +y
min a 使得z的取值均匀分布
* (2) 由于 x,y 都是在[1,m]之前取值, 所以a能取的最小值
* 为m。
* (3) 当a=m时,z的取值范围为 [m+1, m*(m+1)]
* 若z=z-5, 则z的取值范围就变成了 [1, m*m],并且是均匀分布
* (4) 此时,我们的问题就简化成了将[1,m*m]区间的值映射到[1,n]
* (5) 采用“舍去法”, 令 re = m*m mod n,可知多余元素的个数
当z的值为(m*m-re, m*m]时,递归进行新的随机数生成,否则进行步骤6
* (6) 将[1, m*m -re] 均匀分成n份, 每份的间隔为 gap = (m*m -re)/n;
*********************************************/
int Rand_mn(int m,int n)
{
int rand1 = RandM(m), rand2 = RandM(m);
int temp = m*rand2 + rand1; int re = m*m%n; // 多余个数
int gap =(m*m -re)/n; // 取值间隔 if((m+)*m-re<temp && temp<=m*(m+)) // 需要舍弃的部分
return Rand_mn(m,n);
else
return (temp - m -)/gap +; //返回随机结果
} int main()
{
int m,n;
srand((unsigned )time(NULL));
while(cin>>m>>n)
{
int t=;
while(t--) cout<<Rand_mn(m,n)<<endl;
cout<<endl;
}
return ;
}
面试题:给定一个函数rand()能产生1到m之间的等概率随机数,产生1到n之间等概率的随机数?的更多相关文章
- 给定一个函数rand()能产生0到n-1之间的等概率随机数,问如何产生0到m-1之间等概率的随机数?
题目:给定一个函数rand()能产生1到n之间的等概率随机数,问如何产生1到m之间等概率的随机数? 先把问题特殊化,例如原题变为给定一个函数rand5(),该函数可以随机生成1-5的整数,且生成概率一 ...
- 面试题-->写一个函数,返回一个数组中所有元素被第一个元素除的结果
package com.rui.test; import java.util.Random; /** * @author poseidon * @version 1.0 * @date:2015年10 ...
- 谷歌笔试题--给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含), 指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数。
谷歌笔试题--给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含), 指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数. Google2009华南地 ...
- js数据类型的检测总结,附面试题--封装一个函数,输入任意,输出他的类型
一.javascript 中有几种类型的值 1.基本数据类型 : 包括 Undefined.Null.Boolean.Number.String.Symbol (ES6 新增,表示独一无二的值) 特点 ...
- ytu 1050:写一个函数,使给定的一个二维数组(3×3)转置,即行列互换(水题)
1050: 写一个函数,使给定的一个二维数组(3×3)转置,即行列互换 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 154 Solved: 112[ ...
- 用JAVA写一个函数,功能例如以下: 随意给定一组数, 找出随意数相加之后的结果为35(随意设定)的情况
用JAVA写一个函数.功能例如以下:随意给定一组数,比如{12,60,-8,99,15,35,17,18},找出随意数相加之后的结果为35(随意设定)的情况. 能够递归算法来解: package te ...
- 面试题:给定一个长度为N的数组,其中每个元素的取值范围都是1到N。判断数组中是否有重复的数字
题目:给定一个长度为N的数组,其中每个元素的取值范围都是1到N.判断数组中是否有重复的数字.(原数组不必保留) 方法1.对数组进行排序(快速,堆),然后比较相邻的元素是否相同.时间复杂度为O(nlog ...
- Java笔试题:给定一个ReadOnlyClass的对象roc,能否把这个对象的age值改成30?
在Java笔试面试中,经常会遇到代码题,今天我们就来看一则Java代码笔试题. 有如下代码: Class ReadOnlyClass { private Integer age=20; public ...
- /编写一个函数,要求从给定的向量A中删除元素值在x到y之间的所有元素(向量要求各个元素之间不能有间断), 函数原型为int del(int A ,int n , int x , int y),其中n为输入向量的维数,返回值为删除元素后的维数
/** * @author:(LiberHome) * @date:Created in 2019/2/28 19:39 * @description: * @version:$ */ /* 编写一个 ...
随机推荐
- Swift 修改UITextField.Placeholder颜色
StoreNameEditTextField.attributedPlaceholder = NSAttributedString(string:"点此处输入门店名称",attri ...
- 读《分布式一致性原理》zookeeper运维
1.配置详解 1.1基本配置 基本参数包括clientPort,dataDir和tickTime 1.2高级配置 下面我们再来看看zookeeper中一些高级配置参数的配置实用 2.四字命令 我们曾经 ...
- [转] 从数据库中读取图片并导入Excel文件,C#方式
原文地址, 作者 Lvyou1980 直接源码吧. using System; using System.IO; using System.Data; using System.Drawing; us ...
- python学习——练习题(13)
""" 题目:打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身.例如:153是一个" ...
- <转> win7下破解已安装的VS2008
http://renfan.blog.51cto.com/3466724/754301 在win7系统下,已安装的VS2008维护界面是不显示序列号输入的,需要按以下步骤进行才能破解 1.点击“卸载/ ...
- iPhone开发随想:rand()还是arc4random()
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://bj007.blog.51cto.com/1701577/544006 今天在iP ...
- spring与mybatis
- Camera’s Depth Texture
[Camera’s Depth Texture] In Unity a Camera can generate a depth or depth+normals texture. This is a ...
- JS中深拷贝数组、对象、对象数组方法(转载)
我们在JS程序中需要进行频繁的变量赋值运算,对于字符串.布尔值等可直接使用赋值运算符 “=” 即可,但是对于数组.对象.对象数组的拷贝,我们需要理解更多的内容. 首先,我们需要了解JS的浅拷贝与深拷贝 ...
- cdoj913-握手 【Havel定理】
http://acm.uestc.edu.cn/#/problem/show/913 握手 Time Limit: 2000/1000MS (Java/Others) Memory Limit ...