用不规则的木桩执行随机抽奖而没有循环?

时间:2018-08-22 14:59:13

标签: algorithm loops

以下是伪代码。

float totalStakes = 0; float [] partnerStakes [];

int EnterDraw(float _stakes) {
    totalStakes += _stakes;
    participantStakes.push(_stakes);
    return participantStakes.length - 1;
}

int SelectWinner() {
    float rnd = Random(0, totalStakes);
    float sum = 0;
    for(int i=0; i<participantStakes.length; i++) {
        sum += participantStakes[i];
        if (rnd <= sum) {
            return i;
        }
    }
}

bool DidIWin(int _participantID) {
    return (SelectWinner() == i);
}

此伪代码运行抽奖活动,参与者有不同的获胜概率。 我的问题是,是否有任何方法可以执行此操作而不必潜在地遍历所有元素?

重要:随机数仅在所有参与者都进入抽奖之后生成。

1 个答案:

答案 0 :(得分:1)

我同意这样的评论:如果仅存储赌注的数量,就无法避免在数组中循环,而我的回答基于@juvian的评论。

我没有为每个数组存储桩数,而是为每个参与者存储了索引范围。这样,就不依赖于数组其他元素中的值。从那里进行二进制搜索以找到获胜指数。

搜索中的一项调整是从相对于获胜赌注价值的位置开始,再到总赌注而不是绝对中点。因此,这在以正态分布的数据集的情况下应该会表现更好。

int EnterDraw(float _stakes) {
    totalStakes += _stakes;
    min = (pStakes.length > 0) ? pStakes[pStakes.length - 1].cutoff : 0;
    cutoff = min + _stakes;
    pStakes.push({ min, cutoff });
    return pStakes.length - 1;
}

int SelectWinner() {
    float rnd = Random(0, totalStakes);
    int i = floor(pStakes.length * rnd / totalStakes);
    int high = totalStakes - 1;
    int low = 0;
    while (!(pStakes[i].min <= rnd && pStakes[i].max > rnd) {
      if (pStakes[i].min > rnd) {
        high = i - 1;
        i = floor((i - low) / 2) + low;
      }
      else {
        low = i + 1;
        i = floor((high - i) / 2) + low;
      }
    }
    return i;
}