虽然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之间等概率的随机数?的更多相关文章

  1. 给定一个函数rand()能产生0到n-1之间的等概率随机数,问如何产生0到m-1之间等概率的随机数?

    题目:给定一个函数rand()能产生1到n之间的等概率随机数,问如何产生1到m之间等概率的随机数? 先把问题特殊化,例如原题变为给定一个函数rand5(),该函数可以随机生成1-5的整数,且生成概率一 ...

  2. 面试题-->写一个函数,返回一个数组中所有元素被第一个元素除的结果

    package com.rui.test; import java.util.Random; /** * @author poseidon * @version 1.0 * @date:2015年10 ...

  3. 谷歌笔试题--给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含), 指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数。

    谷歌笔试题--给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含), 指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数. Google2009华南地 ...

  4. js数据类型的检测总结,附面试题--封装一个函数,输入任意,输出他的类型

    一.javascript 中有几种类型的值 1.基本数据类型 : 包括 Undefined.Null.Boolean.Number.String.Symbol (ES6 新增,表示独一无二的值) 特点 ...

  5. ytu 1050:写一个函数,使给定的一个二维数组(3×3)转置,即行列互换(水题)

    1050: 写一个函数,使给定的一个二维数组(3×3)转置,即行列互换 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 154  Solved: 112[ ...

  6. 用JAVA写一个函数,功能例如以下: 随意给定一组数, 找出随意数相加之后的结果为35(随意设定)的情况

    用JAVA写一个函数.功能例如以下:随意给定一组数,比如{12,60,-8,99,15,35,17,18},找出随意数相加之后的结果为35(随意设定)的情况. 能够递归算法来解: package te ...

  7. 面试题:给定一个长度为N的数组,其中每个元素的取值范围都是1到N。判断数组中是否有重复的数字

    题目:给定一个长度为N的数组,其中每个元素的取值范围都是1到N.判断数组中是否有重复的数字.(原数组不必保留) 方法1.对数组进行排序(快速,堆),然后比较相邻的元素是否相同.时间复杂度为O(nlog ...

  8. Java笔试题:给定一个ReadOnlyClass的对象roc,能否把这个对象的age值改成30?

    在Java笔试面试中,经常会遇到代码题,今天我们就来看一则Java代码笔试题. 有如下代码: Class ReadOnlyClass { private Integer age=20; public ...

  9. /编写一个函数,要求从给定的向量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:$ */ /* 编写一个 ...

随机推荐

  1. update project maven项目的时候出错

    preference node "org.eclipse.wst.validation"has been remove 上面的错误是因为修改包名无法互相引入导致的,仅仅需要将Ecl ...

  2. Spring实战之通过XML装配bean

    尽管Spring长期以来确实与XML有着关联,但现在需要明确的是,XML不再是配置Spring的唯一可选方案.Spring现在有了强大的自动化配置和基于Java的配置,XML不应该再是你的第一选择了. ...

  3. html 中的media属性

    在css中我们使用media标签来区分调用哪个css样式,比如使用media="print"来表示当执行打印文档时,使用print.css样式.这样使得文档更有得于打印,如将页面宽 ...

  4. MFC单文档分割区(CSplitterWnd)

    用VS08程序向导,单文档程序,默认设置生成的.工程名为3view; 其中默认生成的视图类CMy3viewView,对应3viewView.h,3viewView.cpp; 在Resourse Vie ...

  5. Synchronized块同步变量的误区

    我们可以通过synchronized块来同步特定的静态或非静态方法.要想实现这种需求必须为这些特性的方法定义一个类变量,然后将这些方法的代码用synchronized块括起来,并将这个类变量作为参数传 ...

  6. 【302】C# TreeView 控件使用说明

    参考:C# 中treeview 树节点图标的动态加载,及选中时图标改变 参考:C# TreeView 控件的综合使用方法 参考:TreeView 类 参考:TreeNode 类 1. 添加根和子级 通 ...

  7. PHP - 闭包Closure和lambda function

    现在的语言没有闭包简直都不好意思说出来. 想要了解闭包是什么,那么就必须知道匿名函数.其实看起来他们其实差不多一个意思. 见php RFC一句话:   End of 2007 a patch was  ...

  8. MySQL数据库篇之索引原理与慢查询优化之一

    主要内容: 一.索引的介绍 二.索引的原理 三.索引的数据结构 四.聚集索引与辅助索引 五.MySQL索引管理 六.测试索引 七.正确使用索引 八.联合索引与覆盖索引 九.查询优化神器--explai ...

  9. GameObject.Find 使用技巧

    GameObject.Find是全局搜索 如果你已经知道这个元件在哪个元件里面的话,且担心场景中有重名元件,可以这样写 GameObject.Find ("Canvas/Panel/Imag ...

  10. ios-loadView

      // 先判断当前控制器是不是从storyBoard中加载,如果是,就会加载stroyBoard的view //   判断是否是xib加载 // 否则创建一个空白的view // 如果重写了此方法, ...