《剑指 Offer》专项突破版 - 面试题 71 : 按权重生成随机数(C++ 实现)

题目链接LCR 071. 按权重随机选择 - 力扣(LeetCode)

题目

给定一个正整数数组 w,其中 w[i] 代表下标 i 的权重(下标从 0 开始),请写一个函数 pickIndex,它可以随机地获取下标 i,选取下标 i 的概率与 w[i] 成正比。

例如,对于 w = [1, 2, 3, 4],选取下标 0 的概率为 1 / (1 + 2 + 3 + 4) = 0.1(即 10%),选取下标 1 的概率为 2 / 10 = 0.2(即 20%),选取下标 3 的概率为 3 / 10 = 0.3(即 30%),选取下标 4 的概率为 4 / 10 = 0.4(即 40%)。

分析

创建一个和权重数组 w 的长度一样的数组 sums,其中 sums[i] 是权重数组中前 i 个数字之和。例如,累加权重数组 [1, 2, 3, 4] 中的权重得到的数组 sums 为 [1, 3, 6, 10]。

有了这个累加权重的数组之后,等概率地生成 1 到 10 之间的一个随机数 p,如果 p <= 1,则选取下标 0;如果 1 < p <= 3,则选取下标 1;如果 3 < p <= 6,则选取下标 2;如果 6 < p <= 10,则选取下标 3

也就是说,随机生成 p 之后,找到数组 sum 中第一个大于或等于 p 的值,然后选取它对应的下标

代码实现

class Solution {
public:
    Solution(vector<int>& w) {
        int n = w.size();
        sum.resize(n);
        sum[0] = w[0];
        for (int i = 1; i < n; ++i)
        {
            sum[i] = w[i] + sum[i - 1];
        }
    }
    
    int pickIndex() {
        int p = rand() % sum.back() + 1;
​
        int left = 0;
        int right = sum.size() - 1;
        while (left < right)
        {
            int mid = (left + right) / 2;
            if (sum[mid] < p)
                left = mid + 1;
            else  // sum[mid] >= p
                right = mid;
        }
        return right;
    }
private:
    vector<int> sum;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值