Random pick with weight index

528.Random Pick with Weight

Prefix Sum
Math

Problem Statement:

Given an array w of positive integers, where w[i] describes the weight of index i, implement the function pickIndex() which randomly picks an index in proportion to its weight.

Example:

Input:

["Solution","pickIndex"] [[[1,3]],[]]

Output:

[null,1]

Java Solution:

// Extremeley easy problem, see solution for more info but heres a summary:
// Basically use preSum array and binary search of the keep searching varation
// 1. Get prefix sum array of weights
// 2. Generate random index from sum of all weights
// 3. Search for smallest index that is less than the random
class Solution {

    Random random;
    int[] wSums;  // Store prefix sums
    
    public Solution(int[] w) {
        this.random = new Random();
        for(int i=1; i// Build prefix sum array
        
        this.wSums = w;
    }
    
    public int pickIndex() {
        int len = wSums.length;
        int idx = random.nextInt(wSums[len-1]) + 1; // Random index from sum of all weights combined
        int left = 0, right = len - 1;
        int ans = 0;
        // search position
        while(left <= right){
            int mid = left + (right-left)/2;
            if(wSums[mid] == idx)
                return mid;
            else if (idx > wSums[mid])
                left = mid + 1;
            else {
               // If less, set ans and keep searching left
               ans = mid;
               right = mid - 1;
            }
        }
        return ans;
    }
}

Python Solution:

class Solution:
    def __init__(self, w: List[int]):
        # Build prefix sum array
        self.prefix = []
        prefix_sum = 0
        for weight in w:
            prefix_sum += weight
            self.prefix.append(prefix_sum)
        
    def pickIndex(self) -> int:
        target = random.randint(1, self.prefix[-1])
        left, right = 0, len(self.prefix) - 1
        
        # Binary search for target weight
        while left < right:
            mid = (left + right) // 2
            if self.prefix[mid] >= target:
                right = mid
            else:
                left = mid + 1
                
        return left

C++ Solution:

class Solution {
private:
    vector<int> prefix;
    
public:
    Solution(vector<int>& w) {
        // Build prefix sum array
        prefix = w;
        for(int i = 1; i < w.size(); i++)
            prefix[i] += prefix[i-1];
    }
    
    int pickIndex() {
        int target = rand() % prefix.back() + 1;
        return lower_bound(prefix.begin(), prefix.end(), target) - prefix.begin();
    }
};
Previous
Previous

Subarray Sums Equals k [PRefix Sum]

Next
Next

Lowest Common Ancestor of a Binary Tree III