面试题精选:Rand10()实现Rand7()

简介: 前两天在刷leetcode的时候,遇到了一题Implement Rand10() Using Rand7(),rand7()可以给你等概率返回1-7的任意一个数,让你用rand7()实现一个rand10(),rand()可以等概率返回1-10的任意一个数。后来又在上网中不经意看到了另一题rand5()实现rand7(),更早些,我自己面试的过程中也遇到过类似的题。再早些在大二的时候,有个学姐在群里问过的一道她遇见的一道类似的面试题,我们先来从这道题开始,逐步剖析这种randX()–>randY()的题目怎么做。

前两天在刷leetcode的时候,遇到了一题Implement Rand10() Using Rand7(),rand7()可以给你等概率返回1-7的任意一个数,让你用rand7()实现一个rand10(),rand()可以等概率返回1-10的任意一个数。后来又在上网中不经意看到了另一题rand5()实现rand7(),更早些,我自己面试的过程中也遇到过类似的题。再早些在大二的时候,有个学姐在群里问过的一道她遇见的一道类似的面试题,我们先来从这道题开始,逐步剖析这种randX()–>randY()的题目怎么做。

 当年网协有个09级的学姐面试时遇到一个问题,有个unFairRand()函数以80%的概率返回0,20%的概率返回1,请在unFairRand()的基础上实现一个fairRand(),能够以50% 50%的概率返回0和1,不允许使用各其他random函数。当时我给出了一个正确的解答,但没做过详细分析。

 我的解答是这样的,用两次调unFairRand结果的组合来返回0或者1,两次结果是01就返回0,10就返回1,00或者11就重新算一次。01和10的概率都是16%。算一次就返回0和1的概率是32%,但还有68%的可能再算一次。不过不用担心,我们构造的函数不管内部计算多少次,只要返回1或者0,其概率是一样的,这也满足题目要求,代码如下。


 

    public int fairRand() {
        int x = unFairRand();
        int y = unFairRand();
        if (x == 1 && y == 0) {
            return 1;
        }
        else if (x == 0 && y == 1) {
            return 0;
        } else {
            return fairRand();
        }
    }

这时候让你算下,调用一次fairRand()后,unFairRand()被调用的期望是多少?公式如下,这个公式可以化简,貌似是高中的知识了,感觉我是化不出来了。


E = 0.32 ∗ 2 + 0.68 ∗ 0.32 ∗ 4 + 0.68 ∗ 0.32 ∗ 6 + . . . . + 0.6 8 ( n − 1 ) ∗ 0.32 ∗ 2 n    ( n → ∞ ) E = 0.32*2 + 0.68*0.32*4 + 0.68*0.32*6 + .... +0.68^{(n-1)}*0.32*2n \ \ (n \rightarrow \infty)

E=0.32∗2+0.68∗0.32∗4+0.68∗0.32∗6+....+0.68

(n−1)

∗0.32∗2n  (n→∞)


 接下来我们直接看下leetcode上这道Implement Rand10() Using Rand7(),rand10()除了严格等概率返回1-10之外,起始还限制你尽可能少调用rand7()。

 调用两次加在一起,然后模10+1?貌似1-10的数字都有了,来看下分布表。

 52a8034744a0f21089a7a86ba4b5e2f4_70.png

 明显可以看出,1-10每个数字分布肯定不是相等的。我们必须构造出一数表,使得1-10任意一个数在表里出现的频率是一样的,如下,构造出一个连续数表就可以了。

 58435a786280982c1c2391d2c8530c33_70.png

 如何构造,(rand7()-1)*7 + rand7(),就可以了,为什么是乘以7而不是6或者8,如果乘以其他的数,数表里的数就会有缺失或则重复计算,概率必然不一样了。举个例子,乘以8,14、15就多出现了。

 Implement Rand10() Using Rand7()的解答如下。

    public int rand10() {
        int x = (rand7()-1)*7 + rand7();
        return x<=40 ? x%10 +1 : rand10();
    }


如果是rand5–>rand7呢?简单


    public int rand7() {
        int x = (rand5()-1)*5 + rand5();
        return x<=21 ? x%7 + 1 : rand7();
    }

为什么上面分别是x<=40和x<=21,而不是其他数字里,起始rand10里10,20,30,40都可以,rand7里7,14,21都可以。回顾下题目还有另一个要求,尽可能少调用给你的rand函数,从概率的角度来看,取的数越大,需要再次计算的几率就越小,调用给定函数的次数就越少。

 至于调用次数的期望,我只给出rand7计算rand10的期望表达,rand5->rand7就留给你算了。

E = 2 ∗ 40 42 + 4 ∗ 2 42 ∗ 40 42 + . . . . + 2 n ∗ ( 2 42 ) n − 1 ∗ 40 42       ( n → ∞ ) E = 2*\frac{40}{42} + 4*\frac{2}{42}*\frac{40}{42} +....+2n*(\frac{2}{42})^{n-1}*\frac{40}{42} \ \ \ \ \ (n \rightarrow \infty)

E=2∗

42

40

+4∗

42

2

42

40

+....+2n∗(

42

2

)

n−1

42

40

     (n→∞)


 如果是randM --> randN (M < N)呢?也简单。


    public int randN() {
        int x = (randM()-1)*M + randM();
        return x <= N*a ? x%N +1 : randN(); //这里a是使得调用次数最少的一个系数
    }
目录
相关文章
|
3月前
|
JSON 搜索推荐 API
小红书笔记列表API数据解析(附代码)
本内容介绍如何利用小红书开放平台的笔记列表API,批量获取与关键词或用户相关的笔记数据,包括标题、封面图、互动数据等。接口支持按关键词分页查询及排序筛选,适用于内容聚合与用户分析。附Python示例代码,演示通过GET请求调用API的方法,并处理返回的JSON数据。
|
3月前
|
JSON API 数据格式
小红书笔记详情API数据解析(附代码)
本内容介绍了小红书开放平台的笔记详情API接口功能,涵盖笔记标题、内容、互动数据及多媒体资源的获取方式。提供接口概述、请求方式及Python调用示例,适用于内容分析与营销策略优化,帮助开发者高效集成与使用。
|
8月前
|
机器学习/深度学习 算法
广义优势估计(GAE):端策略优化PPO中偏差与方差平衡的关键技术
广义优势估计(GAE)由Schulman等人于2016年提出,是近端策略优化(PPO)算法的核心理论基础。它通过平衡偏差与方差,解决了强化学习中的信用分配问题,即如何准确判定历史动作对延迟奖励的贡献。GAE基于资格迹和TD-λ思想,采用n步优势的指数加权平均方法,将优势函数有效集成到损失函数中,为策略优化提供稳定梯度信号。相比TD-λ,GAE更适用于现代策略梯度方法,推动了高效强化学习算法的发展。
1024 3
广义优势估计(GAE):端策略优化PPO中偏差与方差平衡的关键技术
|
JSON API 数据格式
网易云音乐随机歌曲调用API接口
网易云音乐随机歌曲调用API接口
|
数据挖掘
InsTag:大语言模型监督微调数据标签标注工具
魔搭社区发布了一个名为“InsTagger”的工具,用于分析LLM(大语言模型)中符合人类偏好的监督微调(SFT)数据。InsTagger 是基于 InsTag 方法训练的本地指令标签标注器,用于为符合人类偏好的监督微调数据集中的指令标注描述其意图和语义的标签,从而指导指令的分流或监督微调数据集的分析。
|
12月前
|
Web App开发 XML 移动开发
HTML5 MathML
HTML5 支持 MathML,用于显示数学公式,通过 `&lt;math&gt;` 标签实现。MathML 是基于 XML 的标准,但目前仅 Firefox 和 Safari 浏览器支持。其他浏览器可借助第三方库如 mspace.js 来实现兼容。示例代码展示了如何使用 MathML 显示勾股定理、二次方程及矩阵。
|
Docker 容器
docker设置国内镜像源
docker设置国内镜像源
36869 5
|
分布式计算 并行计算 数据处理
大规模数据处理的最佳实践:使用 Dask 进行高效并行计算
【8月更文第29天】在大数据时代,高效地处理大规模数据集是至关重要的。Python 社区提供了一些强大的工具来帮助开发者进行并行和分布式计算,其中之一就是 Dask。本文将详细介绍如何使用 Dask 来优化大规模数据集的处理效率,并提供一些实用的代码示例。
1998 3
|
安全 JavaScript 前端开发
某论坛新游试玩区被植入利用ANI漏洞传播 Trojan.Mnless.kip 的代码
某论坛新游试玩区被植入利用ANI漏洞传播 Trojan.Mnless.kip 的代码
|
存储 安全 Java
利用POI多线程导出数据错位解决
通过反射替换解决
952 0