[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 ...
随机推荐
- jQuery AJAX 方法 success()后台传来的4种数据
JAVA中的四种JSON解析方式详解 jQuery AJAX 方法 success()后台传来的4种数据 1.后台返回一个页面 js代码 /**(1)用$("#content-wrapper ...
- 使用 https://git.io 缩短 a GitHub.com URL.
curl -i https://git.io -F 'url=https://develon2015.github.io' -F 'code=develon' 现在点击 http://git.io/d ...
- JavaScript 的正则也有单行模式了
正则表达式最早是由 Ken Thompson 于 1970 年在他改进过的 QED 编辑器里实现的,正则里最简单的元字符 “.” 在当时所匹配的就是除换行符外的任意字符: "." ...
- Ubuntu 18.04 LTS搭建GO语言开发环境
一.下载Go语言安装包 官网下载地址:https://golang.org/dl/,使用tar命令将档案包解压到/usr/local目录中: sudo tar -C /usr/local -xzf g ...
- PnP 问题方程怎么列?
PnP 问题即 Perspective-n-Point . 有 P3P 方法,使用三个点对就能求解.但是先按照熟悉的方法,写一写.最后写 P3P 方法,P3P 方法还是比较晦涩的,不是无脑方法. 1. ...
- Docker: repository, image, container
1. 查看image: docker images 2. 查看信息: docker info 3. 搜索image: docker search [image_name], 比如: docker se ...
- java接口自动化基础知识(二)
二.HttpClient+testNG实现对接口的测试及校验 在上面第一篇中已经实现了基础配置和测试用例数据准备,本篇文章将以登录举例进行测试执行. 这是之前login接口的代码 @Test(grou ...
- vue-地址插件 v-region
demo地址:https://terryz.gitee.io/vue/#/region/demo
- jquery 第三章
1.回顾$(document).ready(function(){ })$(function(){ }) ID选择器.类选择器.元素选择器层次选择器:空格(上文下:tr td{})属性过滤 ...
- Redis数据类型Hash
Redis的Hash有点像一个对象(object),一个Hash里面可以存多个Key-Value对作为它的field,所以它通常可以用来表示对象.Hash里面能存放的值也能作为String类型来存储, ...