求解概率均等的随机数

随机返回0到n中非m的整数,只调用一次rand,概率均等
int f = rand()
如何让f变为[0,n)中非m的整数,要概率均等,mE[0,n)
当时面试官说用概率做,分布到n-1个数上,然后交换位置什么的,完全没听懂

就是说,随机到m的时候,这个数不能要,要把它变成别的数
既然要概率均等,那么如果你一开始就随机的是[0,n),那么m变成任何别的数,那个数的概率就会加倍
所以一开始就要随机[0,n-1)的范围,遇到m就把它改成n-1,这样概率就均等了
当然你也可以一开始随机[1,n),遇到m变0
-=-=-=-=-=
其实这道题答案是什么根本不重要
重要的是遇到一个问题的时候如何思考
如果题目只告诉你[0,n)范围随机,这题就太简单了
而m不要,它会有什么问题,要从问题出发
如果可以随机多次,那么随机到m就重新随机,这没有问题
而如果只能随机一次,随机到m的时候你总不能丢弃吧,要把它变成另一个数返回
思考到这里答案基本已经很显而易见了
要么你把m变成0,要么把m变成n-1,要么把m变成m+1,答案并不唯一,但是思路其实是一样的

为了随机返回一个在区间 [0, n) 中非 m 的整数,可以使用以下方法:

  1. 计算有效整数的数量:首先,确定在 [0, n) 区间内除去 m 后的有效整数数量,即 count = n - 1。因为 m 被排除在外,所以有效整数的数量减少了一个。

  2. 生成随机数 r:使用一次 rand() 函数生成一个随机数 r。

  3. 调整随机数 r 的范围:将随机数 r 通过模运算取余数,即 r = r % count。这样可以将 r 的范围限定在 [0, count) 区间内。

  4. 处理结果:如果 r 大于等于 m,则需要对结果进行适当的调整。可以将 r 的值加一,使其跳过 m,即 r = r + 1。

  5. 返回最终结果:返回 r 作为结果。

下面是使用 C++ 实现的示例代码:

#include <iostream>
#include <cstdlib>
#include <ctime>

int getRandomNonM(int n, int m) {
    int count = n - 1; // 有效整数的数量
    int r = rand() % count; // 随机数范围在 [0, count)
    if (r >= m) {
        r++; // 跳过 m
    }
    return r;
}

int main() {
    srand(static_cast<unsigned>(time(0))); // 初始化随机数种子

    int n = 10; // 区间 [0, n)
    int m = 5; // 排除的数 m

    int result = getRandomNonM(n, m);
    std::cout << "Random non-" << m << " number: " << result << std::endl;

    return 0;
}

这段代码中,使用 srand() 函数初始化随机数种子,确保每次运行时都会得到不同的随机数序列。然后,调用 getRandomNonM() 函数传入区间的上界 n 和要排除的数 m,即可得到符合要求的随机非 m 整数。最后,输出结果即可。

这种方法通过将随机数映射到有效整数范围,然后通过适当的调整来确保概率均等,并且只调用一次 rand() 函数。