题目:
黑名单中的随机数
个人思路:
直接得到0~n范围一个随机数,然后判断是不是在黑名单里面,不在的话就输出,在的话就重复执行pick()函数。缺点很明显,如果得到了一个随机数在黑名单中,那我们就需要重新得到一个随机数,最坏的情况需要执行m次随机数获取,与题意不符。
参考思路:
使用映射,假设把0 ~ n-1的数字分成两个部分,0 ~ n-m部分是白名单,n-m ~ n是黑名单,m是黑名单元素个数。这样我们得到了一个随机数,直接判断他是不是在黑名单,不是的话就直接输出,是的话就输出白名单里的数字,而输出白名单里哪个数字,就需要用映射来决定。
映射很容易想到使用哈希几何,C++中体现就是map
代码:
class Solution {
public:
Solution(int n, vector& blacklist) {
bound = n-blacklist.size();
unordered_set black; //存储黑名单
for(int num:blacklist)
{
if(num >= bound)
{
black.emplace(num);
}
}
int w = bound;
for(int num:blacklist)
{
if(num < bound)
{
while(black.count(w))
w++;
map[num] = w++; //把前半部分的黑名单数字num映射到后半部分的白名单数字w
}
}
}
int pick()
{
//srand(time(0));
int num = rand()%bound; //获得0~n-1范围内的随机数
return map.count(num)?map[num]:num; //是白名单,就输出;不是,就输出map中的映射
}
private:
int bound; //黑白名单分割线
unordered_map map; //map,存储映射
};
十年饮冰,难凉热血



