Given a blacklist B containing unique integers from [0, N), write a function to return a uniform random integer from [0, N) which is NOT in B.

Optimize it such that it minimizes the call to system’s Math.random().

Note:

  1. 1 <= N <= 1000000000
  2. 0 <= B.length < min(100000, N)
  3. [0, N) does NOT include N. See interval notation.

Example 1:

Input:
["Solution","pick","pick","pick"]
[[1,[]],[],[],[]]
Output: [null,0,0,0]

Example 2:

Input:
["Solution","pick","pick","pick"]
[[2,[]],[],[],[]]
Output: [null,1,1,1]

Example 3:

Input:
["Solution","pick","pick","pick"]
[[3,[1]],[],[],[]]
Output: [null,0,0,2]

Example 4:

Input:
["Solution","pick","pick","pick"]
[[4,[2]],[],[],[]]
Output: [null,1,3,1]

Explanation of Input Syntax:

The input is two lists: the subroutines called and their arguments. Solution's constructor has two arguments, N and the blacklist Bpick has no arguments. Arguments are always wrapped with a list, even if there aren't any.

这道题让我们生成一个N以内的随机数,但是还给了一个黑名单,意思是黑名单里面的数字不能被选到。于是博主最先想到的方法就是用拒绝采样Rejection Sampling来做,因为之前做过使用该方法的两道题 Implement Rand10() Using Rand7() 和 Generate Random Point in a Circle,所以可以立马想到。思路其实很简单,就是随机一个数,如果是黑名单里的,那么就重新随机。为了提高在黑名单中查找数字的速度,我们将所有黑名单的数字放到一个HashSet中,这样我们就拥有了常数级查找的速度,看似一切水到渠成,燃鹅被OJ强行打脸,TLE!那么换一种思路吧,既然你有黑名单,那么林北就有白名单,把所有没被block的数字都放到一个新数组中,然后随机生成数组坐标不就完了。燃鹅x2,又被OJ放倒了,MLE!不准用这么多内存。岂可修,真的没别的办法了嘛?!还好方法解答贴中给了一种使用HashMap的方法来做,博主仔细研读了一番,发现确实秒啊!既然数字总共有N个,那么减去黑名单中数字的个数,就是最多能随机出来的个数。比如N=5,黑名单中有两个数{2, 4},那么我们最多只能随机出三个,但是我们如果直接rand()%3,会得到0,1,2,我们发现有两个问题,一是黑名单中的2可以随机到,二是数字3没法随机到。那么我们想,能不能随机到0或1则返回其本身,而当随机到2到时候,我们返回的是3,我们需要建立这样的映射,这就是使用HashMap的动机啦。我们首先将超过N - blacklist.size()的数字放入一个HashSet,这里就把{3, 4}放进去了,然后我们遍历blacklist中的数字,如果在HashSet中的话,就将其删除,这样HashSet中就只有{3}了,这个需要建立映射的数字,而用什么数字建立,当然是用黑名单中的数字了,遍历黑名单中的数字,如果小于N - blacklist.size()的话,说明是有可能随机到的,我们和HashSet中的第一个数字建立映射,然后我们可以用个iterator,指向HashSet中的下一个数组,然后继续建立映射。从而实现在pick函数中的移魂换影大法了,先随机个数字,如果有映射,则返回映射值,否则返回原数字,参见代码如下:

class Solution {
public:
Solution(int N, vector<int> blacklist) {
unordered_set<int> st;
len = N - blacklist.size();
for (int i = len; i < N; ++i) st.insert(i);
for (int num : blacklist) st.erase(num);
auto it = st.begin();
for (int num : blacklist) {
if (num < len) m[num] = *it++;
}
} int pick() {
int k = rand() % len;
return m.count(k) ? m[k] : k;
} private:
unordered_map<int, int> m;
int len;
};

类似题目:

Random Pick with Weight

Random Pick Index

参考资料:

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

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

[LeetCode] Random Pick with Blacklist 带黑名单的随机选取的更多相关文章

  1. 710. Random Pick with Blacklist - LeetCode

    Question 710. Random Pick with Blacklist Solution 题目大意:给一个N,表示一个范围[0,N),给一个黑名单列表blacklist,其中blacklis ...

  2. [LeetCode] Random Pick with Weight 根据权重随机取点

    Given an array w of positive integers, where w[i] describes the weight of index i, write a function  ...

  3. [Swift]LeetCode710. 黑名单中的随机数 | Random Pick with Blacklist

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

  4. 710 Random Pick with Blacklist

    1. 问题 给定一个黑名单,包含[0, N)的一些数,从[0, N)之间的非黑名单数中随机采样一个值. 2. 思路 字典映射 (1)计算黑名单数的长度,记作B,因为已经排除掉了B个元素,所以最后是从N ...

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

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

  6. Leetcode: Random Pick Index

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

  7. LeetCode 528. Random Pick with Weight

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

  8. 398. Random Pick Index - LeetCode

    Question 398. Random Pick Index Solution 思路:重点是如果数据中有多个数target相等,要从这些数中随机取一个,根据例题 假设输入是: int[] nums ...

  9. [LeetCode] Random Point in Non-overlapping Rectangles 非重叠矩形中的随机点

    Given a list of non-overlapping axis-aligned rectangles rects, write a function pick which randomly ...

随机推荐

  1. Java 基础知识点

    很多 Java 基础的东西都忘记了, 有必要再复习一些基本的知识点. 本文主要参考 https://github.com/Snailclimb/JavaGuide ================== ...

  2. 个人认为一个比较完整,基于tp5平台,可快速开发的B2C平台

    现在全民创业,做电商的人很多,大大小小的技术公司也很多,报价也很奇葩,从100到十万的都有,把人都能转晕,有朋友问我,你们创业是不是很赚钱,其实,外行不知道内行的苦,创业控制成本第一,活下来才能赚钱. ...

  3. Fast R-CNN(理解)

    0 - 背景 经典的R-CNN存在以下几个问题: 训练分多步骤(先在分类数据集上预训练,再进行fine-tune训练,然后再针对每个类别都训练一个线性SVM分类器,最后再用regressors对bou ...

  4. jsonp跨域ajax跨域get方法

    原理: 就是利用<script >标签没有跨域限制的,从而达到与第三方网站通讯的目的.当需要通讯时,本站脚本创建一个<script>标签,src地址指向第三方网站的的一个网址. ...

  5. find xargs 简单组合使用

    简单总结下,留作自己以后拾遗...... 一.find xargs 简单组合 ## mv 小结find ./ -type f -name "*.sh"|xargs mv -t /o ...

  6. how2heap学习笔记

    github源代码地址 这里只分析glibc2.25堆分配的特性,为了方便调试编译时使用 gcc -g -no-pie <input_file_name> -o <output_fi ...

  7. 【原创】大叔问题定位分享(19)spark task在executors上分布不均

    最近提交一个spark应用之后发现执行非常慢,点开spark web ui之后发现卡在一个job的一个stage上,这个stage有100000个task,但是绝大部分task都分配到两个execut ...

  8. 【原创】大叔问题定位分享(17)spark查orc格式数据偶尔报错NullPointerException

    spark查orc格式的数据有时会报这个错 Caused by: java.lang.NullPointerException at org.apache.hadoop.hive.ql.io.orc. ...

  9. Java面试题复习笔记(前端)

    1.Html,CSS,Jsp在网页开发中的定位? Html——定义网页结构(超文本标记语言) CSS——层叠样式表,用来美化界面 Jsp——主要用来验证表单,做动态交互(Ajax) 2.介绍Ajax? ...

  10. unity 网页加载AB问题

    下载一次后会缓存,清理一下就能加载新的同名AB了 AssetBundle.onload