Random Pick with Blacklist - Problem
Random Pick with Blacklist

You're building a lottery system that needs to randomly select winners from a pool of participants, but some participants are disqualified (blacklisted). Your task is to design an efficient algorithm that can randomly pick a valid participant.

Given an integer n representing the total number of participants (numbered from 0 to n-1) and an array blacklist containing the IDs of disqualified participants, you need to:

1. Initialize your system with the total count and blacklist
2. Pick random participants efficiently, ensuring each valid participant has an equal chance

The key challenge is to minimize random function calls while maintaining perfect randomness. Each call to pick() should return a random integer in [0, n-1] that's not blacklisted.

Example:
If n = 7 and blacklist = [2, 3, 5], valid participants are [0, 1, 4, 6]. Each should have a 25% chance of being selected.

Input & Output

example_1.py โ€” Basic Usage
$ Input: n = 7, blacklist = [2, 3, 5] Operations: ["Solution", "pick", "pick", "pick", "pick"]
โ€บ Output: Valid returns: any of [0, 1, 4, 6] for each pick
๐Ÿ’ก Note: With n=7, we have indices [0,1,2,3,4,5,6]. Removing blacklisted [2,3,5] leaves [0,1,4,6]. Each pick() should return one of these 4 values with equal probability (25% each).
example_2.py โ€” Edge Case Small
$ Input: n = 4, blacklist = [1, 3] Operations: ["Solution", "pick", "pick"]
โ€บ Output: Valid returns: any of [0, 2] for each pick
๐Ÿ’ก Note: Only 2 valid numbers remain out of 4. The virtual array maps: original [0,1,2,3] with blacklist [1,3] becomes effective range [0,2) where index 1 is mapped to value 2.
example_3.py โ€” Heavy Blacklist
$ Input: n = 10, blacklist = [0, 1, 2, 3, 4, 5, 6] Operations: ["Solution", "pick", "pick", "pick"]
โ€บ Output: Valid returns: any of [7, 8, 9] for each pick
๐Ÿ’ก Note: Most numbers are blacklisted, leaving only [7,8,9]. The algorithm efficiently maps the small valid range [0,3) to these tail values, avoiding expensive rejection sampling.

Visualization

Tap to expand
๐ŸŽฏ The Lottery Ticket Rearrangement StrategyBefore: Random draws often hit invalid tickets โŒXโœ“XXโœ“Random draws waste time on invalid ticketsAfter: Virtual rearrangement ensures every draw hits valid tickets โœ…Safe Draw Zone [0, validCount)0โ†’412โ†’63โ†’7Substitution Source4567๐ŸŽฒ The Magic: One Random Draw = One Valid Result1. Generate: rand(4) โ†’ could be 0, 1, 2, or 32. Lookup: mapping[2] = 6, others return as-is โ†’ results: 4, 1, 6, 7โšก Always O(1) time, perfect distribution!๐Ÿ’ก Key Insight: Transform the problem from "avoid bad numbers" to "directly map to good numbers"
Understanding the Visualization
1
Count Valid Tickets
Calculate how many valid tickets exist: validCount = n - blacklist.length
2
Identify Problem Tickets
Find blacklisted tickets in positions [0, validCount) - these block our random draw
3
Create Substitutions
Map each problematic ticket to a valid ticket from positions [validCount, n)
4
Draw and Substitute
Generate random in [0, validCount), apply substitution if needed
Key Takeaway
๐ŸŽฏ Key Insight: Instead of rejection sampling (which wastes random calls), create a virtual mapping that transforms any random number in [0, validCount) into a valid result. This guarantees O(1) performance and perfect uniform distribution!

Time & Space Complexity

Time Complexity
โฑ๏ธ
O(b) initialization, O(1) per pick

Preprocessing takes O(blacklist_size), each pick is constant time with one random call

n
2n
โœ“ Linear Growth
Space Complexity
O(b)

Store mapping for blacklisted numbers that fall in [0, validCount) range

n
2n
โœ“ Linear Space

Constraints

  • 1 โ‰ค n โ‰ค 109
  • 0 โ‰ค blacklist.length โ‰ค min(105, n - 1)
  • 0 โ‰ค blacklist[i] < n
  • All values in blacklist are unique
  • At most 2 ร— 104 calls will be made to pick
Asked in
Google 45 Amazon 38 Meta 25 Microsoft 18
28.4K Views
Medium Frequency
~35 min Avg. Time
892 Likes
Ln 1, Col 1
Smart Actions
๐Ÿ’ก Explanation
AI Ready
๐Ÿ’ก Suggestion Tab to accept Esc to dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen