leetcode 528. 按权重随机选择

给你一个下标从 0 开始 的正整数数组 w,其中 w[i] 代表第 i 个下标的权重。

请你实现一个函数 pickIndex,它可以随机地从范围 [0, w.length - 1] 内(含 0 和
w.length - 1)选出并返回一个下标。选取下标 i 的概率 为 w[i] / sum(w) 。

例如,对于 w = [1, 3],挑选下标 0 的概率为 1 / (1 + 3) = 0.25(即,25%),而选取下标 1 的概率为 3 / (1 + 3) = 0.75(即,75%)。

rand()

Generate random number
Returns a pseudo-random integral number in the range between 0 and RAND_MAX.

rand() % n 产生范围为[0, n)中的随机数。

举例分析

假设给定数组w=[1, 2, 3]。挑选下标0的概率为 1/(1+2+3)=1/6,而选取下标1的概率为2/(1+2+3)=2/6,选取下标2的概率为3/6。

使用线段长度表示下标0、1和2出现的概率,如下图所示:
图片.png

(0, 6]区间总长为6,那么取(0, 6]范围内的随机数,该随机数落在(0,1]、(1,3]和(3,6]区间内的概率分别为1/6、2/6和3/6,即满足权值概率要求。
其中,区间分段点1、3、6即为前缀和

此处我们可以仅考虑随机数为整数的情况:(0, 6]区间内随机数为1属于(0,1];2、3属于(1,3];4、5、6属于(3,6]。

随机产生一个数字,然后使用二分法查找>=该数的最小值在前缀和中的位置,即为下标。

代码

class Solution {
public:
    vector<int> s;
    Solution(vector<int>& w) {
        s = w;
        int n = w.size();
        for (int i = 1; i < n; i++) s[i] += s[i - 1];
    }
    
    int pickIndex() {
        int x = rand() % s.back() + 1; // 随机数范围[1...s.back()]
        return lower_bound(s.begin(), s.end(), x) - s.begin();
    }
};

应用场景

彩票调度算法[操作系统]
https://pages.cs.wisc.edu/~re...


zahlenw2
1 声望0 粉丝

引用和评论

0 条评论