给定一个公平硬币的功能,为有偏见的硬币写一个函数?

时间:2010-01-11 09:16:43

标签: puzzle

我在做一些评论时遇到了这个报道的面试问题(以下引用是我发现的有关问题的所有信息):

  

鉴于公平硬币的功能,   为有偏见的硬币写一个函数   返回头1 / n次(n是a   PARAM)

乍一看,我写道:

int biased_coin(n) { //0=Tails, 1=Heads
  int sum = 0;

  if(n==1)
    return 1;

  for(int i=0;i<n;i++) {
    sum += unbiased(); //unbiased returns 0 50% of the time and 1 50% of the time
  }

  if(sum == 1)
    return 1;

  return 0;
}

但这显然不起作用。例如,对于n = 4,它确实起作用:因为给出4个投掷的单个头的概率是4 /(2 ^ 4)= 1/4。但是对于说n = 3,3 /(2 ^ 3)!= 1/3。

假设你不能使用随机数生成器,实现这样的东西的正确方法是什么?

3 个答案:

答案 0 :(得分:10)

假设:

int fairCoinToss();

为头部返回1,为尾部返回2,写作:

int biasedCoinToss(int n);

其中head(1)将出现1 / n的时间:

int biasedCoinToss(int n) {
  if (n == 1) {
    return 1; // 1/1 = 1 = always heads
  } else if (n == 2) {
    return fairCoinToss(); // 1/2 = 50% = fair coint oss
  }
  int r = random_number(n);
  return r == 0 ? 1 : 0;
}

其中random_number(n)生成一个公平的随机整数i,使得0 <= i < n。因此random_number(3)为0,1或2.假设均匀分布,则值0将在1/3的时间内出现。

当然我们不能使用本机随机数生成器,但我们无论如何都可以创建一个。 fairCoinToss()随机生成1或0.可以组合多个硬币投掷以生成更大的数字。例如:

fairCoinToss() << 1 | fairCoinToss()

将生成:

00 = 0
01 = 1
10 = 2
11 = 3

根据定义是从0到3(n = 4)的随机数。

如果n是2的幂,那就没关系,但不一定如此。然而,这很容易满足。假设n = 5.最多我们可以生成一个从0到7的随机数。如果你“重新”5,6或7,直到得到一个0到4范围内的数字,那么你(非确定性地)构造了一个随机数公平分布在0到4之间,满足要求。

代码看起来像这样:

int random_number(int n) {
  int ret;
  do {
    int limit = 2;
    ret = fairCoinToss();
    while (limit < n) {
      ret <<= 1;
      ret |= fairCoinToss();
      limit <<= 1;
    }
  } while (ret >= n);
  return ret;
}

答案 1 :(得分:2)

这个怎么样:
1.找出n
的二进制表示 2.翻转公平的硬币登录时间。每个翻盖对应一点。
3.如果翻转的结果大于n的值,则重新滚动。
4.如果结果为0,则返回头部。
5.否则,返回尾巴。

答案 2 :(得分:0)

由于N的大多数值不是2的幂,因此不能严格地保证任意数量的硬币投掷的概率为1 / N.相反,你必须满足接近1 / N的东西,达到你想要的准确度。但是,嘿,无论如何,这都是扔给你的硬币。

绘制一个决策树,在根部标记2个分支(标记为H和T),然后在每个节点(也标记为H和T)分支2个分支,直到达到足够的叶节点以满足您的准确度要求。使用您想要的值标记正确(适合您)叶子的部分,例如,如果N = 3,则为1,2,3。然后每个叶子定义一个来自根的路由,例如HHHTTHH(或其他)。这些定义了导致'3'的投掷顺序。

我会把编码留给你。