【Leetcode】528. Random Pick with Weight

题目地址:

https://leetcode.com/problems/random-pick-with-weight/

给定一个长 n n n的数组 A A A A [ i ] A[i] A[i]表示 i i i的重复次数,要求设计一个类,可以在 0 ∼ n − 1 0\sim n-1 0n1 n n n个数里,随机挑选数,使得 x x x的出现概率恰好等于 A [ i ] / ∑ i A [ i ] A[i]/\sum_i A[i] A[i]/iA[i]

思路是利用前缀和,开一个新数组 p p p,其长也为 n n n,并且满足 p [ 0 ] = A [ 0 ] , p [ i ] − p [ i − 1 ] = A [ i ] p[0]=A[0], p[i]-p[i-1]=A[i] p[0]=A[0],p[i]p[i1]=A[i]。挑选数的过程可以这样做,先利用均匀分布随机变量产生一个 0 ∼ A [ n − 1 ] − 1 0\sim A[n-1]-1 0A[n1]1的随机数 x x x,然后找到第一个下标 k k k使得 A [ k ] > x A[k]>x A[k]>x,则这次挑选出的数即为 k k k。显然 0 0 0被选择的概率就是 p [ 0 ] p [ n − 1 ] = A [ 0 ] ∑ i A [ i ] \frac{p[0]}{p[n-1]}=\frac{A[0]}{\sum_i A[i]} p[n1]p[0]=iA[i]A[0]对于别的数 c c c被选择的概率就是 p [ c ] − p [ c − 1 ] p [ n − 1 ] = A [ c ] ∑ i A [ i ] \frac{p[c]-p[c-1]}{p[n-1]}=\frac{A[c]}{\sum_i A[i]} p[n1]p[c]p[c1]=iA[i]A[c]符合条件。而找到第一个 A [ k ] > x A[k]>x A[k]>x k k k,可以通过二分法得到。代码如下:

class Solution {
 public:
  vector<int> p;

  Solution(vector<int>& w) {
    srand(time(nullptr));
    p.resize(w.size());
    p[0] = w[0];
    for (int i = 1; i < w.size(); i++)
      p[i] = p[i - 1] + w[i];
  }

  int pickIndex() {
    int idx = rand() % p.back();
    int l = 0, r = p.size() - 1;
    while (l < r) {
      int mid = l + (r - l >> 1);
      if (p[mid] > idx) r = mid;
      else l = mid + 1;
    }
    return l;
  }
};

预处理时间复杂度 O ( n ) O(n) O(n),每次询问时间 O ( log ⁡ n ) O(\log n) O(logn),空间 O ( n ) O(n) O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值