Random Pick with Weight - Complete Solution Guide
Random Pick with Weight is LeetCode problem 528, a Medium level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
You are given a 0-indexed array of positive integers w where w[i] describes the weight of the i th index. You need to implement the function pickIndex() , which randomly picks an index in the range [0, w.length - 1] ( inclusive ) and returns it. The probability of picking an index i is w[i] / sum(w) . For example, if w = [1, 3] , the probability of picking index 0 is 1 / (1 + 3) = 0.25 (i.e., 25% ), and the probability of picking index 1 is 3 / (1 + 3) = 0.75 (i.e., 75% ). Example 1: Input ["Sol
Detailed Explanation
The problem requires us to implement a `pickIndex()` function that randomly selects an index from an array `w` of positive integers. Each integer `w[i]` represents the weight or probability of picking index `i`. The probability of selecting index `i` is proportional to its weight, specifically `w[i] / sum(w)`. In other words, indices with higher weights are more likely to be selected. The constructor takes the array `w` as input and the `pickIndex` function must return a randomly chosen index based on the given weights.
Solution Approach
The solution utilizes the prefix sum technique and binary search. First, the constructor calculates the prefix sums of the input weight array `w`. The prefix sum at index `i` represents the sum of weights from index 0 to `i`. This transforms the problem of picking an index based on weight into a problem of finding which range a random number falls into. Then, when `pickIndex()` is called, a random integer between 1 and the total sum of all weights is generated. Binary search is then used on the prefix sums array to find the first index whose prefix sum is greater than or equal to the random number. This index is then returned as the selected index.
Step-by-Step Algorithm
- Step 1: **Constructor (`__init__` in Python, `Solution` in Java/C++)**: Calculate the prefix sums of the weight array `w`. Store these prefix sums in a separate array (`prefix_sums`). Also, calculate and store the total sum of all weights in `total_sum`.
- Step 2: **`pickIndex()`**: Generate a random integer `target` between 1 and `total_sum` (inclusive). In C, seed the random number generator in the constructor.
- Step 3: **Binary Search**: Perform binary search on the `prefix_sums` array to find the smallest index `i` such that `prefix_sums[i]` is greater than or equal to `target`.
- Step 4: **Return Index**: Return the index `i` found in the binary search.
Key Insights
- Insight 1: Using prefix sums allows for efficient binary search to determine the index corresponding to a randomly generated number within the total weight range.
- Insight 2: Employing binary search optimizes the `pickIndex` function to achieve a logarithmic time complexity.
- Insight 3: Precalculating and storing the prefix sums avoids redundant calculations in each `pickIndex` call.
Complexity Analysis
Time Complexity: O(log n)
Space Complexity: O(n)
Topics
This problem involves: Array, Math, Binary Search, Prefix Sum, Randomized.
Companies
Asked at: Coinbase, Criteo, Liftoff, Netflix, PayPal, Remitly, Revolut, Rubrik, Shopee, Snap, Snowflake, Sony, Two Sigma, X, Yelp.