Map Weighted Random Draws to Indices
NuroSoftware Engineer · Technical ScreenLast updated
This problem tests your ability to efficiently map a series of random draws to specific indices based on provided weights using binary search techniques.
Problem Statement
You are tasked with building a weighted random sampler. Given an array of positive integers weights, where weights[i] represents the weight of index i, you must process a series of draws (numbers between 1 and the total sum of all weights).
Your goal is to implement a class WeightedSampler that maps each draw to the corresponding index. A draw $x$ maps to index $i$ if the cumulative sum of weights up to index $i-1$ is strictly less than $x$, and the cumulative sum up to index $i$ is greater than or equal to $x$.
Implementation Interface
class WeightedSampler:
def __init__(self, weights: list[int]):
# Initialize data structures for efficient lookup
pass
def get_index(self, draw: int) -> int:
# Map the draw to an index (0-indexed)
pass
Constraints
- `1 <= len(weights) 0 (Range [1, 1])
get_index(2)-> 1 (Range [2, 4])get_index(4)-> 1 (Range [2, 4])get_index(6)-> 2 (Range [5, 6])
Edge Cases
- Single element in
weights. drawvalues exactly equal to cumulative boundary points.
Hints
Hint 1
Consider precomputing the prefix sums of the weights array to define ranges for each index.
Hint 2
The prefix sum array will be monotonically increasing, allowing you to use binary search to locate the correct interval.
Hint 3
Use the 'bisect_left' logic to find the first index in the prefix sum array where the value is greater than or equal to the draw.
Follow-up questions
- How would you optimize the solution if the weights array changes frequently and you need to perform many updates?
- What is the time complexity of the initialization and the query operation?
- How would you handle a scenario where the weights are floating-point numbers instead of integers?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.