710. Random Pick with Blacklist
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 <= N <= 1000000000
0 <= B.length < min(100000, N)
[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 B
. pick
has no arguments. Arguments are always wrapped with a list, even if there aren't any.
AC code:
class Solution { private: int N; vector<int> blacklist; unordered_set<int> blackSet; random_device rd; mt19937 gen; uniform_int_distribution<> dist; int findMap(int y) { int l = 0, r = N - 1; // need to find lower_bound // 二分真是一件Tricky的事情 while (l < r) { int mid = (l + r) / 2; int smaller = upper_bound(blacklist.begin(), blacklist.end(), mid) - blacklist.begin(); if (mid - smaller < y) l = mid + 1; else r = mid; } return l; } public: Solution(int N, vector<int> blacklist): gen(rd()), dist(0, N - blacklist.size() - 1) { this->N = N; this->blacklist = blacklist; sort(this->blacklist.begin(), this->blacklist.end()); for (int b: blacklist) blackSet.insert(b); } int pick() { int r = dist(gen); int m = findMap(r); // cout << r << ' ' << m << endl; // 事实证明,保证lower_bound之后,找到的数必然不是黑名单中的数 /* while (blackSet.find(m) != blackSet.end()) m++; */ return m; } }; /** * Your Solution object will be instantiated and called as such: * Solution obj = new Solution(N, blacklist); * int param_1 = obj.pick(); */
I can't understand this question's intention.
永远渴望,大智若愚(stay hungry, stay foolish)