【字节跳动】数据挖掘面试题0004: 一个随机整数产生器产生[1,5],如何设计一个产生[1,7]的随机整数产生器。

文章大纲

    • 题目描述
      • 方法思路
      • 具体实现
      • 方法解释
      • 数学原理
      • 通俗类比解释
        • 第一步:从 1-5 到 0-4
        • 第二步:创造 "更大的骰子"
        • 第三步:给棋盘编号
        • 第四步:压缩到 1-7
        • 第五步:处理 "无效数字"
      • 总结:`完成解决方案流程`

题目描述

  • 要基于一个生成范围在 [1, 5] 的随机整数生成器来设计出能生成 [1, 7] 随机整数的生成器,可按以下步骤操作:

方法思路

  • 借助原有的生成器生成两个相互独立的随机数,范围都是 [1, 5]。
  • 把这两个随机数组合起来,构建一个更大的等概率空间,这里能得到 25 种不同的组合情况。
  • 对这 25 种组合进行映射,让其中 21 种组合均匀地对应到 [1, 7] 的数字上。
  • 要是生成的组合落在剩下的 4 种情况里,就重新进行生成操作。

具体实现

import random

def rand5():
    return random.randint(1, 5)

def rand7():
    while True:
        # 生成范围为[0, 24]的随机数
        num = (rand5() - 1) * 5 + (rand5() - 1)
        # 仅当随机数小于21时进行映射
        if num < 21:
            return num % 7 + 1

方法解释

    1. 构建更大的随机空间:通过公式(rand5() - 1) * 5 + (rand5() - 1),能够得到 [0, 24] 范围内的均匀分布随机数。
    1. 映射到目标范围:当随机数处于 [0, 20] 这个区间时,对其取模并加 1,就可以将其转换为 [1, 7] 的均匀分布。
    1. 处理超出范围的情况:如果生成的随机数是 21 到 24,就重新生成,以此保证每个数字的生成概率相等。

数学原理

  • 由于每个原始随机数的生成概率都是 1/5,所以 25 种组合里每种组合出现的概率都是 1/25。
  • 把 21 种组合平均分成 7 组,每组有 3 种组合,那么每组出现的概率就是 3/25,也就是每个目标数字的生成概率为 1/7。
  • 虽然存在重新生成的情况,但从数学期望上来说,该算法的时间复杂度是 O (1)。

我来用更通俗的方式解释这个问题。我们可以把这个过程想象成玩一个 “升级骰子” 的游戏:

通俗类比解释

第一步:从 1-5 到 0-4

假设你有一个特殊的 5 面骰子(数字 1-5),但我们需要先把它变成 “0-4 点数” 的骰子。方法很简单:每次掷出后减 1。比如:

掷出 1 → 变成 0

掷出 2 → 变成 1

以此类推,掷出 5 → 变成 4
第二步:创造 “更大的骰子”

现在我们有两个 0-4 的骰子,怎么组合成更大的随机数呢?可以把它们想象成一个5x5 的棋盘:

第一次掷骰子的结果(0-4)作为棋盘的行

第二次掷骰子的结果(0-4)作为棋盘的列

每个格子的坐标就是 (行,列),比如 (2,3)(4,0)
第三步:给棋盘编号

我们给这个 5x5 的棋盘里的每个格子编一个号,从 0 开始,一直到 24。编号规则很简单:

  • 格子编号 = 行 ×5 + 列
    比如:
    左上角 (0,0) → 编号 0×5 + 0 = 0
    
    中间 (2,2) → 编号 2×5 + 2 = 12
    
    右下角 (4,4) → 编号 4×5 + 4 = 24
    

这样我们就得到了一个范围 0-24 的 “超级随机数生成器”!

第四步:压缩到 1-7

现在我们需要把 0-24 的数字变成 1-7。方法是:

  • 只保留 0-20 的数字(因为 21-24 不够分)

  • 对 7 取余数再加 1
    比如:

    00%7 +1 = 1
    
    66%7 +1 = 7
    
    77%7 +1 = 1
    
    1313%7 +1 = 7
    
    2020%7 +1 = 7
    
第五步:处理 “无效数字”

如果掷出的数字是 21-24 怎么办?很简单:重新掷骰子!直到得到 0-20 的数字为止。

总结:完成解决方案流程

  • 掷两次 5 面骰子,分别得到 A 和 B
  • 计算 (A-1)×5 + (B-1),得到 0-24 的数字
  • 如果结果≥21,回到第 1 步
  • 否则,计算 结果%7 +1,得到 1-7 的数字

这样就能保证每个数字(1-7)出现的概率完全相等!

你可能感兴趣的:(数据挖掘常见面试题,python,随机数,算法面试题)