ou are given an array of positive integers w
where w[i]
describes the weight of i
th
index (0-indexed).
We need to call the function pickIndex()
which randomly returns an integer in the range [0, w.length - 1]
. pickIndex()
should return the integer proportional to its weight in the w
array. For example, for w = [1, 3]
, the probability of picking the index 0
is 1 / (1 + 3) = 0.25
(i.e 25%) while the probability of picking the index 1
is 3 / (1 + 3) = 0.75
(i.e 75%).
More formally, the probability of picking index i
is w[i] / sum(w)
.
Example 1:
Input ["Solution","pickIndex"] [[[1]],[]] Output [null,0] Explanation Solution solution = new Solution([1]); solution.pickIndex(); // return 0. Since there is only one single element on the array the only option is to return the first element.
Example 2:
Input ["Solution","pickIndex","pickIndex","pickIndex","pickIndex","pickIndex"] [[[1,3]],[],[],[],[],[]] Output [null,1,1,1,1,0] Explanation Solution solution = new Solution([1, 3]); solution.pickIndex(); // return 1. It's returning the second element (index = 1) that has probability of 3/4. solution.pickIndex(); // return 1 solution.pickIndex(); // return 1 solution.pickIndex(); // return 1 solution.pickIndex(); // return 0. It's returning the first element (index = 0) that has probability of 1/4. Since this is a randomization problem, multiple answers are allowed so the following outputs can be considered correct : [null,1,1,1,1,0] [null,1,1,1,1,1] [null,1,1,1,0,0] [null,1,1,1,0,1] [null,1,0,1,0,0] ...... and so on.
Constraints:
1 <= w.length <= 10000
1 <= w[i] <= 10^5
pickIndex
will be called at most10000
times.
Answer: I just copied answer with top vote. Good idea to convert scale of sum to scale 1. Please checkout my comment below.
Btw, Random r = new Random(); r.nextInt(i); // return integer between [0, i)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | class Solution { // explain probabilities[i]: // Math.random() is to randomly pick an value from 0 to 1 // We need to convert from scale 1 to scale sum // so that any value of Math.random() corresponds to 1 portion of scale sum // in below formula, w[i] is the original value of w // probabilities[i] - probabilities[i - 1] == w[i]/sum // which means in portion i, its length is w[i]/sum, in the scale of 0 to 1 // And this is the weighted probability in scale of 0 to 1 private double[] probabilities; public Solution(int[] w) { double sum = 0; this.probabilities = new double[w.length]; for(int weight : w) sum += weight; for(int i = 0; i < w.length; i++){ w[i] += (i == 0) ? 0 : w[i - 1]; probabilities[i] = w[i]/sum; } } public int pickIndex() { // Arrays.binarySearch returns the index of 1st bigger element return Math.abs(Arrays.binarySearch(this.probabilities, Math.random())) - 1; } } /** * Your Solution object will be instantiated and called as such: * Solution obj = new Solution(w); * int param_1 = obj.pickIndex(); */ |
No comments:
Post a Comment