528. 按权重随机选择 - 力扣(LeetCode)
还是类似蓄水池抽样问题:
LeetCode第 382 题:链表随机节点(C++)_zj-CSDN博客
LeetCode第 398 题:随机数索引(C++)_zj-CSDN博客
这儿需要考虑数组值,也就是权重,权重越大,被选取的概率也就越大。
但是代码一直超时。。。
class Solution {
public:
Solution(vector& w) {
p = &w;
}
int pickIndex() {//返回值应该是位置(下标)
int sum = 0, res = 0;//pre记录上一次的sum
for(int i = 0; i < p->size(); ++i){
sum += (*p)[i];
if(rand()%sum >= sum - p[i]) res = i;
}
return res;
}
private:
vector* p;
};
好吧,看了题解之后才发现理解错题意了。这题并不像蓄水池抽样问题,也没有提到数组很大或者数据流之类的字眼。所以前缀和 + 二分就可以:
class Solution {
public:
Solution(vector& w){
//最后p里面存储的是w的前缀和,因为元素是正整数
//所以p的首元素为最小值,尾元素为最大值
p = w;
for(int i = 1; i < p.size(); ++i) p[i] = p[i] + p[i-1];//累加
}
int pickIndex() {//返回值应该是位置(下标)
int i = rand() % p.back()+1;//随机1~p.back()之间的某个数
return lower_bound(p.begin(), p.end(), i) - p.begin();//二分
}
private:
vector p;
};