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. 1 <= w.length <= 10000
  2. 1 <= w[i] <= 10^5
  3. pickIndex will be called at most 10000 times.

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 wpickIndex 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 Pick Index

Random Pick with Blacklist

Random Point in Non-overlapping Rectangles

参考资料:

https://leetcode.com/problems/random-pick-with-weight/discuss/154024/JAVA-8-lines-TreeMap

https://leetcode.com/problems/random-pick-with-weight/discuss/154772/C%2B%2B-concise-binary-search-solution

https://leetcode.com/problems/random-pick-with-weight/discuss/154044/Java-accumulated-freq-sum-and-binary-search

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Random Pick with Weight 根据权重随机取点的更多相关文章

  1. [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  ...

  2. 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 ...

  3. select random item with weight 根据权重随机选出

    http://eli.thegreenplace.net/2010/01/22/weighted-random-generation-in-python/ 类似俄罗斯轮盘赌

  4. [LeetCode] Random Pick with Blacklist 带黑名单的随机选取

    Given a blacklist B containing unique integers from [0, N), write a function to return a uniform ran ...

  5. LeetCode 528. Random Pick with Weight

    原题链接在这里:https://leetcode.com/problems/random-pick-with-weight/ 题目: Given an array w of positive inte ...

  6. 528. Random Pick with Weight

    1. 问题 给定一个权重数组w,w[i]表示下标i的权重,根据权重从数组中随机抽取下标. 2. 思路 这道题相当于 497. Random Point in Non-overlapping Recta ...

  7. [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  ...

  8. 【LeetCode】528. Random Pick with Weight 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址:https://leetcode.com/problems/random-pi ...

  9. [LeetCode] Random Pick Index 随机拾取序列

    Given an array of integers with possible duplicates, randomly output the index of a given target num ...

随机推荐

  1. 第五节: EF高级属性(一) 之 本地缓存、立即加载、延迟加载(不含导航属性)

    一. 本地缓存 从这个章节开始,介绍一下EF的一些高级特性,这里介绍的首先介绍的EF的本地缓存,在前面的“EF增删改”章节中介绍过该特性(SaveChanges一次性会作用于本地缓存中所有的状态的变化 ...

  2. updateXML 注入 python 脚本

    用SLQMAP来跑updateXML注入发现拦截关键字,然后内联注入能绕,最后修改halfversionedmorekeywords.py脚本,结果SQLMAP还是跑不出来.>_< hal ...

  3. DCM、PLL、PMCD、MMCM相关

    摘自网上 : http://xilinx.eetop.cn/viewnews-1482 The DCM is a Digital Clock Manager - at its heart it is ...

  4. Laravel 多数据库配置及查询操作

    laravel文档好像没有写得很详细 https://docs.golaravel.com/docs/5.3/database/ Using Multiple Database Connections ...

  5. springboot ****使用经验*******

    目录 1. 返回时间格式化问题 2. springboot 中获取属性 3. SpringBoot中启动是忽略某项检测 4.  启动不开启安全校验 一返回时间格式化问题 在Spring Boot项目中 ...

  6. Postman 安装及使用入门教程(我主要使用接口测试)

    1.Postman 安装及使用入门教程(我主要使用接口测试)Postman的English官网:https://www.getpostman.com/chrome插件整理的Postman中文使用教程( ...

  7. Angular组件——投影

    运行时动态改变组件模版的内容.没路由那么复杂,只是一段html,没有业务逻辑. ngContent指令将父组件模版上的任意片段投影到子组件上. 一.简单例子 1.子组件中使用<ng-conten ...

  8. ios 运行时特征,动态改变控件字体大小

    需求:ex: 在不同尺寸的iPhone上面显示的字体大小不一样 https://github.com/rentzsch/jrswizzle #import <UIKit/UIKit.h> ...

  9. mysql的坑

    mysql安装报错: 1.The service already exists! The current server installed: 因为mysql卸载不完全. 解决方法: C:\window ...

  10. python数据类型——数据转换

    数据类型有很多种,比如数值和字符,比如6和a,字符是需要加双引号的,下面的例子运行的结果是不一样的,数值会相加而字符会相连 print(6+6)print("6"+"6& ...