Random Pick with Weight

Similar Problems:

- CheatSheet: Leetcode For Code Interview
- CheatSheet: Common Code Problems & Follow-ups
- Tag: #presum, #binarysearch, #random

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

Note:

- 1 <= w.length <= 10000
- 1 <= w[i] <= 10^5
- pickIndex will be called at most 10000 times.

Example 1:

Input: ["Solution","pickIndex"] [[[1]],[]] Output: [null,0]

Example 2:

Input: ["Solution","pickIndex","pickIndex","pickIndex","pickIndex","pickIndex"] [[[1,3]],[],[],[],[],[]] Output: [null,0,1,1,1,0]

Explanation of Input Syntax:

The input is two lists: the subroutines called and their arguments. Solution's constructor has one argument, the array w. pickIndex has no arguments. Arguments are always wrapped with a list, even if there aren't any.

Github: code.dennyzhang.com

Credits To: leetcode.com

Leave me comments, if you have better ways to solve.

- Solution:

// https://code.dennyzhang.com/random-pick-with-weight // Basic Ideas: presum + binarysearch // // Complexity: Time O(log(n)), Space O(n) import "math/rand" type Solution struct { presums []int } func Constructor(w []int) Solution { presums := make([]int, len(w)) sum := 0 for i, v := range w { sum += v presums[i] = sum } return Solution{presums:presums} } func (this *Solution) PickIndex() int { target := rand.Intn(this.presums[len(this.presums)-1])+1 left, right := 0, len(this.presums) // result must exist in the list for left < right { mid := (right-left)/2+left if this.presums[mid] < target { // search right half left = mid+1 } else { right = mid } } return left } /** * Your Solution object will be instantiated and called as such: * obj := Constructor(w); * param_1 := obj.PickIndex(); */