|
| 1 | +--- |
| 2 | +id: random-pick-with-weight |
| 3 | +title: Random Pick With Weight |
| 4 | +sidebar_label: 0528-Random-Pick-with-Weight |
| 5 | +tags: |
| 6 | +- Array |
| 7 | +- Math |
| 8 | +- Binary Search |
| 9 | +- Prefix Sum |
| 10 | +description: solution to the leetcode problem Random Pick With Weight. |
| 11 | +--- |
| 12 | + |
| 13 | +## Problem |
| 14 | + |
| 15 | +You are given a 0-indexed array of positive integers `w` where `w[i]` describes the weight of the `i`th index. |
| 16 | + |
| 17 | +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)`. |
| 18 | + |
| 19 | +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%). |
| 20 | + |
| 21 | +Sure, here is the markdown with input, output, and explanation all in one go: |
| 22 | + |
| 23 | +### Examples |
| 24 | + |
| 25 | +**Example 1:** |
| 26 | + |
| 27 | +Input: |
| 28 | +``` |
| 29 | +["Solution","pickIndex"] |
| 30 | +[[[1]],[]] |
| 31 | +``` |
| 32 | +Output: |
| 33 | +``` |
| 34 | +[null,0] |
| 35 | +``` |
| 36 | +Explanation: |
| 37 | +``` |
| 38 | +Solution solution = new Solution([1]); |
| 39 | +solution.pickIndex(); // return 0. The only option is to return 0 since there is only one element in w. |
| 40 | +``` |
| 41 | + |
| 42 | +**Example 2:** |
| 43 | + |
| 44 | +Input: |
| 45 | +``` |
| 46 | +["Solution","pickIndex","pickIndex","pickIndex","pickIndex","pickIndex"] |
| 47 | +[[[1,3]],[],[],[],[],[]] |
| 48 | +``` |
| 49 | +Output: |
| 50 | +``` |
| 51 | +[null,1,1,1,1,0] |
| 52 | +``` |
| 53 | +Explanation: |
| 54 | +``` |
| 55 | +Solution solution = new Solution([1, 3]); |
| 56 | +solution.pickIndex(); // return 1. It is returning the second element (index = 1) that has a probability of 3/4. |
| 57 | +solution.pickIndex(); // return 1 |
| 58 | +solution.pickIndex(); // return 1 |
| 59 | +solution.pickIndex(); // return 1 |
| 60 | +solution.pickIndex(); // return 0. It is returning the first element (index = 0) that has a probability of 1/4. |
| 61 | +``` |
| 62 | + |
| 63 | +Since this is a randomization problem, multiple answers are allowed. |
| 64 | +All of the following outputs can be considered correct: |
| 65 | +``` |
| 66 | +[null,1,1,1,1,0] |
| 67 | +[null,1,1,1,1,1] |
| 68 | +[null,1,1,1,0,0] |
| 69 | +[null,1,1,1,0,1] |
| 70 | +[null,1,0,1,0,0] |
| 71 | +...... |
| 72 | +``` |
| 73 | +and so on. |
| 74 | + |
| 75 | +### Constraints |
| 76 | + |
| 77 | +- $1 <= w.length <= 10^4$ |
| 78 | +- $1 <= w[i] <= 10^5$ |
| 79 | +- `pickIndex` will be called at most `10^4` times. |
| 80 | +``` |
| 81 | +
|
| 82 | +
|
| 83 | +## Solution |
| 84 | +
|
| 85 | +```cpp |
| 86 | +class Solution { |
| 87 | + public: |
| 88 | + Solution(vector<int>& w) { |
| 89 | + int last = 0; |
| 90 | + for (auto const& len : w) { |
| 91 | + range.push_back({last, last + len}); |
| 92 | + last += len; |
| 93 | + } |
| 94 | + srand(time(nullptr)); |
| 95 | + } |
| 96 | +
|
| 97 | + int pickIndex() { |
| 98 | + int logical_index = std::rand() % range.back().second; |
| 99 | + int lo = 0, hi = range.size() - 1; |
| 100 | + while (lo <= hi) { |
| 101 | + int mid = (lo + hi)/2; |
| 102 | +
|
| 103 | + if (logical_index >= range[mid].first && logical_index < range[mid].second) { |
| 104 | + return mid; |
| 105 | + } else if (logical_index < range[mid].first) { |
| 106 | + hi = mid - 1; |
| 107 | + } else { |
| 108 | + lo = mid + 1; |
| 109 | + } |
| 110 | + } |
| 111 | + return -1; |
| 112 | + } |
| 113 | + private: |
| 114 | + vector<pair<int, int>> range; |
| 115 | +}; |
| 116 | +``` |
| 117 | + |
| 118 | +```java |
| 119 | +class Solution { |
| 120 | + |
| 121 | + Random random; |
| 122 | + int[] wSums; |
| 123 | + |
| 124 | + public Solution(int[] w) { |
| 125 | + this.random = new Random(); |
| 126 | + for(int i=1; i<w.length; ++i) |
| 127 | + w[i] += w[i-1]; |
| 128 | + this.wSums = w; |
| 129 | + } |
| 130 | + |
| 131 | + public int pickIndex() { |
| 132 | + int len = wSums.length; |
| 133 | + int idx = random.nextInt(wSums[len-1]) + 1; |
| 134 | + int left = 0, right = len - 1; |
| 135 | + // search position |
| 136 | + while(left < right){ |
| 137 | + int mid = left + (right-left)/2; |
| 138 | + if(wSums[mid] == idx) |
| 139 | + return mid; |
| 140 | + else if(wSums[mid] < idx) |
| 141 | + left = mid + 1; |
| 142 | + else |
| 143 | + right = mid; |
| 144 | + } |
| 145 | + return left; |
| 146 | + } |
| 147 | +} |
| 148 | +``` |
| 149 | + |
| 150 | +### Complexity Analysis |
| 151 | + |
| 152 | +- **Time Complexity:** $O(\log N)$ |
| 153 | +- **Space Complexity:** $O(N)$ |
0 commit comments