C++ binary algorithm: random numbers in blacklist

Involving knowledge points

binary search

Title

Given an integer n and a non-duplicate blacklist integer array blacklist . Design an algorithm to select an integer that is not included in the blacklist from any integer in the range [0, n – 1]. Any integer in the above range that is not in the blacklist should have an equal chance of being returned.
Optimize your algorithm so that it minimizes the number of calls to the language’s built-in random functions.
Implement the Solution class:
Solution(int n, int[] blacklist) initializes the integer n and the integer added to the blacklist blacklist
int pick() returns a random integer in the range [0, n – 1] that is not in the blacklist blacklist
Example 1:
enter
[“Solution”, “pick”, “pick”, “pick”, “pick”, “pick”, “pick”, “pick”]
[[7, [2, 3, 5]], [], [], [], [], [], [], []]
output
[null, 0, 4, 1, 6, 1, 0, 4]
explain
Solution solution = new Solution(7, [2, 3, 5]);
solution.pick(); // Return 0, any integer [0,1,4,6] is acceptable. Note that for each call to pick,
// The return probabilities of 0, 1, 4 and 6 must be equal (that is, the probability is 1/4).
solution.pick(); // return 4
solution.pick(); // return 1
solution.pick(); // return 6
solution.pick(); // return 1
solution.pick(); // return 0
solution.pick(); // return 4
Parameter range
1 <= n <= 109
0 <= blacklist.length <= min(105, n - 1)
0 <= blacklist[i] < n
All values in blacklist are different
pick is called at most 2 * 104 times

Wrong solution space complexity exceeded

Analysis

If the enumeration [0,n) is a blacklist, throw it away, otherwise put it in m_vValue. The maximum value of n is 10^9, which must time out.

Code

class Solution {
public:
Solution(int n, vector & amp; blacklist) {
sort(blacklist.begin(), blacklist.end());
auto it = blacklist.begin();
for (int i = 0; i < n; i + + )
{
while ((it != blacklist.end()) & amp; & amp; (*it < i ))
{
+ + it;
}
if ((it != blacklist.end()) & amp; & amp; (*it == i))
{
continue;
}
m_vValue.emplace_back(i);
}
srand(time(nullptr));
}
int pick() {
return m_vValue[rand() % m_vValue.size()];
}
vector m_vValue;
};

Correct solution

Analysis

Let the number of blacklists be m, then the number that can be generated is m_k=n-m. We randomly generate a number r in [0,m_k), and replace it if r is in the blacklist, otherwise return r directly.

Variable explanation

it points to black The first number in the name point that is greater than or equal to m_k. […,it) needs to be replaced. The replacement number must be greater than or equal to m_k, and cannot be in [it,…), and cannot repeat each other. It is easy to solve by repeating each other: iMay increases automatically, and the initial value is equal to m_k, which can ensure that it is greater than or equal to m_k.
tNeedReplace points to the value that needs to be replaced
itBlackList points to Greater than or equal to the minimum value of iMay.

Note

In the initial case, iMay is less than or equal to *itBlackList. If the two are equal, then itBalck + +, so iMay will never be greater than *itBlackList.

Code

class Solution {<!-- -->
public:
Solution(int n, vector<int> & amp; blacklist) {<!-- -->
sort(blacklist.begin(), blacklist.end());
const int m = blacklist.size();
m_k = n - m;
const auto it = std::lower_bound(blacklist.begin(), blacklist.end(), m_k);
auto itNeedReplace = blacklist.begin();
auto itBlackList = it;
int iMay = m_k;
for (; itNeedReplace != it ; + + itNeedReplace)
{<!-- -->
while ((itBlackList != blacklist.end()) & amp; & amp; (iMay == *itBlackList ))
{<!-- -->
iMay++;
+ + itBlackList;
}
m_mReplace[*itNeedReplace] = iMay + + ;
}
srand(time(nullptr));
}
int pick() {<!-- -->
const int r = rand() % m_k;
if (m_mReplace.count(r))
{<!-- -->
return m_mReplace[r];
}
return r;
}
std::unordered_map<int,int> m_mReplace;
int m_k;
};

March 2023 version of the old code

structSGroupInfo
{
SGroupInfo(int tBegin, int tLen, int tTotalLen)
{
begin = tBegin;
len = tLen;
totalLen = tTotalLen;
}
int End()const
{
return begin + len – 1;
}
int begin;
int len;
int totalLen;
};
class Solution {
public:
Solution(int N, vector & amp; blacklist) {
m_iN = N;
m_iMaxRand = N – blacklist.size();
srand(time(nullptr));
std::sort(blacklist.begin(), blacklist.end());
if (blacklist.empty())
{
m_v.emplace_back(0, N, N);
return;
}
for (int i = 0; i < blacklist.size();i + + )
{
const auto & n = blacklist[i];
if (0 == i )
{
const int len = n;
if (len > 0)
{
m_v.emplace_back(0, len, len);
}
}
else
{
const int len = n – blacklist[i-1] – 1;
if (len > 0)
{
const int iPreLen = m_v.empty() ? 0 : m_v.back().totalLen;
m_v.emplace_back(blacklist[i – 1] + 1, len, iPreLen + len);
}
}
}
const int len = m_iN – 1 – blacklist.back();
if (len > 0)
{
const int iPreLen = m_v.empty() ? 0 : m_v.back().totalLen;
m_v.emplace_back(blacklist.back() + 1, len, iPreLen + len);
}
}
int pick() {
const int index = rand() % m_iMaxRand;
auto it = std::lower_bound(m_v.begin(), m_v.end(), index + 1, [](const SGroupInfo & amp; group, const int & amp; x2)
{return group.totalLen < x2; });
return it->begin + (index – (it->totalLen – it->len));
}
vector m_v;
int m_iN;
int m_iMaxRand;
};

Old code in August 2023

class Solution {
public:
Solution(int n, vector & amp; blacklist) {
m_iPickNum = n – blacklist.size();
std::set setHas(blacklist.begin(), blacklist.end());
int iReplace = m_iPickNum;
for (const auto & amp; black : blacklist)
{
if (black >= m_iPickNum)
{
continue;
}
while (setHas.count(iReplace))
{
iReplace + + ;
}
m_mReplace[black] = iReplace + + ;
}
srand(time(nullptr));
}
int pick() {
int iRand = rand() % m_iPickNum;
if (m_mReplace.count(iRand))
{
return m_mReplace[iRand];
}
return iRand;
}
int m_iPickNum;
std::unordered_map m_mReplace;
};

Extended reading

Video course

Effective learning: clear goals, timely feedback, stretching area (appropriate difficulty), you can learn simple courses first, please move to CSDN Academy
, listen to the explanation of Lecturer Baiyin (that is, I).
https://edu.csdn.net/course/detail/38771

If you want to quickly form a battle and share the worries of your boss, please learn C# onboarding training, C++ onboarding training and other courses
https://edu.csdn.net/lecturer/6176

Related downloads

If you want to know the superior learning algorithm, please download the doc version of “Algorithm Book When You Hear the Defects”
https://download.csdn.net/download/he_zhidan/88348653

What I want to say to you
It is a good wish to be happy when you hear the flaws. Discover problems and correct them early to save your boss money.
The origin of the Mohist name: everything is recorded in Mohism.
If the program is a one-stop process, then the algorithm is its key point

Test environment

Operating system: win7 Development environment: VS2019 C++ 17
Or Operating system: win10 Development environment: VS2022 C++ 17