|
4 | 4 |
|
5 | 5 | public class _528 {
|
6 | 6 | public static class Solution1 {
|
| 7 | + /** |
| 8 | + * Credit: https://leetcode.com/problems/random-pick-with-weight/editorial/ |
| 9 | + * <p> |
| 10 | + * Mental gymnastics (which is explained step by step in the above link): |
| 11 | + * 1. picture this to be a ball throwing onto a line from the starting point (0,0); |
| 12 | + * 2. where this ball is going to land on the line is a probability problem, i.e. an offset to the starting point (0,0); |
| 13 | + * 3. we can use prefix sums array to simulate this line (each value in the array is positive as it represents the weight/probability of it being picked, so cannot be zero or negative); |
| 14 | + * 4. we can use Random() to generate a random number called index bounded by the last value of the prefix sums array, i.e. the biggest offset possible; |
| 15 | + * 5. then we can use binary search to find where this random number: index, would fit in the prefix sums array. |
| 16 | + */ |
7 | 17 | Random random;
|
8 |
| - int[] preSums; |
| 18 | + int[] prefixSums; |
9 | 19 |
|
10 | 20 | public Solution1(int[] w) {
|
11 | 21 | this.random = new Random();
|
12 |
| - for (int i = 1; i < w.length; ++i) { |
13 |
| - w[i] += w[i - 1]; |
| 22 | + this.prefixSums = new int[w.length]; |
| 23 | + int prefixSum = 0; |
| 24 | + for (int i = 0; i < w.length; ++i) { |
| 25 | + prefixSum += w[i]; |
| 26 | + prefixSums[i] = prefixSum; |
14 | 27 | }
|
15 |
| - this.preSums = w; |
16 | 28 | }
|
17 | 29 |
|
18 | 30 | public int pickIndex() {
|
19 |
| - int len = preSums.length; |
20 |
| - int idx = random.nextInt(preSums[len - 1]) + 1; |
| 31 | + int len = prefixSums.length; |
| 32 | + int idx = random.nextInt(prefixSums[len - 1]) + 1; |
21 | 33 | int left = 0;
|
22 | 34 | int right = len - 1;
|
23 | 35 | // search position
|
24 | 36 | while (left < right) {
|
25 | 37 | int mid = left + (right - left) / 2;
|
26 |
| - if (preSums[mid] == idx) { |
| 38 | + if (prefixSums[mid] == idx) { |
27 | 39 | return mid;
|
28 |
| - } else if (preSums[mid] < idx) { |
| 40 | + } else if (prefixSums[mid] < idx) { |
29 | 41 | left = mid + 1;
|
30 | 42 | } else {
|
31 | 43 | right = mid;
|
|
0 commit comments