[LeetCode] Random Pick with Weight 根据权重随机取点
Given an array w of positive integers, where w[i] describes the weight of index i, write a function pickIndex which randomly picks an index in proportion to its weight.
Note:
1 <= w.length <= 100001 <= w[i] <= 10^5pickIndexwill be called at most10000times.
Example 1:
Input:
["Solution","pickIndex"]
[[[1]],[]]
Output: [null,0]
Example 2:
Input:
["Solution","pickIndex","pickIndex","pickIndex","pickIndex","pickIndex"]
[[[1,3]],[],[],[],[],[]]
Output: [null,0,1,1,1,0]
Explanation of Input Syntax:
The input is two lists: the subroutines called and their arguments. Solution's constructor has one argument, the array w. pickIndex has no arguments. Arguments are always wrapped with a list, even if there aren't any.
这道题给了一个权重数组,让我们根据权重来随机取点,现在的点就不是随机等概率的选取了,而是要根据权重的不同来区别选取。比如题目中例子2,权重为 [1, 3],表示有两个点,权重分别为1和3,那么就是说一个点的出现概率是四分之一,另一个出现的概率是四分之三。由于我们的rand()函数是等概率的随机,那么我们如何才能有权重的随机呢,我们可以使用一个trick,由于权重是1和3,相加为4,那么我们现在假设有4个点,然后随机等概率取一个点,随机到第一个点后就表示原来的第一个点,随机到后三个点就表示原来的第二个点,这样就可以保证有权重的随机啦。那么我们就可以建立权重数组的累加和数组,比如若权重数组为 [1, 3, 2] 的话,那么累加和数组为 [1, 4, 6],整个的权重和为6,我们 rand() % 6,可以随机出范围 [0, 5] 内的数,随机到 0 则为第一个点,随机到 1,2,3 则为第二个点,随机到 4,5 则为第三个点,所以我们随机出一个数字x后,然后再累加和数组中查找第一个大于随机数x的数字,使用二分查找法可以找到第一个大于随机数x的数字的坐标,即为所求,参见代码如下:
解法一:
class Solution {
public:
Solution(vector<int> w) {
sum = w;
for (int i = ; i < w.size(); ++i) {
sum[i] = sum[i - ] + w[i];
}
}
int pickIndex() {
int x = rand() % sum.back(), left = , right = sum.size() - ;
while (left < right) {
int mid = left + (right - left) / ;
if (sum[mid] <= x) left = mid + ;
else right = mid;
}
return right;
}
private:
vector<int> sum;
};
我们也可以把二分查找法换为STL内置的upper_bound函数,根据上面的分析,我们随机出一个数字x后,然后再累加和数组中查找第一个大于随机数x的数字,使用二分查找法可以找到第一个大于随机数x的数字的坐标。而upper_bound() 函数刚好就是查找第一个大于目标值的数,lower_bound() 函数是找到第一个不小于目标值的数,用在这里就不太合适了,关于二分搜索发的分类可以参见博主之前的博客LeetCode Binary Search Summary 二分搜索法小结,参见代码如下:
解法二:
class Solution {
public:
Solution(vector<int> w) {
sum = w;
for (int i = ; i < w.size(); ++i) {
sum[i] = sum[i - ] + w[i];
}
}
int pickIndex() {
int x = rand() % sum.back();
return upper_bound(sum.begin(), sum.end(), x) - sum.begin();
}
private:
vector<int> sum;
};
讨论:这题有个很好的follow up,就是说当weights数组经常变换怎么办,那么这就有涉及到求变化的区域和问题了,在博主之前的一道 Range Sum Query - Mutable 中有各种方法详细的讲解。只要把两道题的解法的精髓融合到一起就行了,可以参见论坛上的这个帖子。
类似题目:
Random Point in Non-overlapping Rectangles
参考资料:
https://leetcode.com/problems/random-pick-with-weight/discuss/154024/JAVA-8-lines-TreeMap
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Random Pick with Weight 根据权重随机取点的更多相关文章
- [leetcode]528. Random Pick with Weight按权重挑选索引
Given an array w of positive integers, where w[i] describes the weight of index i, write a function ...
- 528. Random Pick with Weight index的随机发生器
[抄题]: Given an array w of positive integers, where w[i] describes the weight of index i, write a fun ...
- select random item with weight 根据权重随机选出
http://eli.thegreenplace.net/2010/01/22/weighted-random-generation-in-python/ 类似俄罗斯轮盘赌
- [LeetCode] Random Pick with Blacklist 带黑名单的随机选取
Given a blacklist B containing unique integers from [0, N), write a function to return a uniform ran ...
- LeetCode 528. Random Pick with Weight
原题链接在这里:https://leetcode.com/problems/random-pick-with-weight/ 题目: Given an array w of positive inte ...
- 528. Random Pick with Weight
1. 问题 给定一个权重数组w,w[i]表示下标i的权重,根据权重从数组中随机抽取下标. 2. 思路 这道题相当于 497. Random Point in Non-overlapping Recta ...
- [Swift]LeetCode528. 按权重随机选择 | Random Pick with Weight
Given an array w of positive integers, where w[i] describes the weight of index i, write a function ...
- 【LeetCode】528. Random Pick with Weight 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址:https://leetcode.com/problems/random-pi ...
- [LeetCode] Random Pick Index 随机拾取序列
Given an array of integers with possible duplicates, randomly output the index of a given target num ...
随机推荐
- [物理学与PDEs]第3章习题7 快、慢及Alfv\'en 特征速度的比较
证明: 当 $H_1\neq 0$ 及 $H_2^2+H_3^2\neq 0$ 时, 快.慢及 Alfv\'en 特征速度 $C_f$, $C_s$ 及 $C_a$ 满足 $$\bex 0<C_ ...
- MyEclipse编码方式设置
1.windows -> Preferences -> general -> Workspace:
- webpack安装异常
webpack中文指南:https://zhaoda.net/webpack-handbook/index.html 今天中午,我用 cnpm install 重新下载了一下项目的依赖,爆了一 ...
- Java同步容器
一.为什么会出现同步容器 Java的集合框架中,主要有四大类别:List,Set,Queue,Map List,Set,Queue接口分别继承了Collection接口,Map本身是一个接口. 注意C ...
- CapsNet胶囊网络(理解)
0 - 背景 Geoffrey Hinton是深度学习的开创者之一,反向传播等神经网络经典算法发明人,他在去年年底和他的团队发表了两篇论文,介绍了一种全新的神经网络,这种网络基于一种称为胶囊(caps ...
- centos6,与centos7对于防火墙的操作
CentOS 6.5 1.开放指定端口/sbin/iptables -I INPUT -p tcp --dport 端口号 -j ACCEPT //写入修改/etc/init.d/iptables ...
- mysql 迁移
背景 这次做oracle数据迁移,也想总结像mysql的数据迁移方式.简单列下吧,因为具体方式网上很多. 方式 可以通过修改mysql.ini的数据文件目录位置方法实现拷贝迁移,此种方式简单 通过备份 ...
- 二阶环路滤波器的matlab 设计
clc; Rs=10*10^6; %码速率 es=0.707; %阻尼系数 fs=8*10^6; %采样频率.系统时钟频率 Bit_Loop_out=27;%环路滤波器输入输出位宽 N=31; %NC ...
- socket.io中 connect与connection的区别
参考网址:https://blog.csdn.net/sinat_18474835/article/details/80115961
- Python学习笔记九
Python学习笔记之九 为什么要有操作系统 管理硬件,提供接口. 管理调度进程,并且将多个进程对硬件的竞争变得有序. 操作系统发展史 第一代计算机:真空管和穿孔卡片 没有操作系统,所有的程序设计直接 ...