1
- /*
2
- https://leetcode.com/problems/random-pick-with-weight/
3
-
4
- SOLUTION 1
5
-
6
- Precomputation
7
- TC: O(N)
8
- SC: O(n + 100) ~ O(n)
9
- Run-time: pickIndex()
10
- TC: O(1)
11
- SC: O(1)
12
- Since we want to randomly select an index but based on the weight / probability,
13
- we need to use the probability score in some way to do that.
14
- Maintain a vector that stores the index values of 'w' array.
15
- For each index, we can calculate the probability and then map it to [1, 100] count,
16
- then add that many entries to idx vector.
17
- Randomly pick a number, since we have put duplicate entries for each index based on the
18
- weight, the probability of a index getting picked will depend on the no. of such elements in
19
- the array and it will work as expected.
20
-
21
-
22
- SOLUTION 2: Binary Search
23
-
24
- Precomputation
25
- TC: O(N)
26
- SC: O(n)
27
- Run-time: pickIndex()
28
- TC: O(logn)
29
- SC: O(1)
30
-
31
- Since we want a way to account for the weight of individual index values,
32
- we can use cummulative sum for that. We store the cummulative sum of all the
33
- weight values. The idea behind cummulative sum is that for a w[i] that has more weight, it will cover more numbers
34
- hence a random number has more chances of falling in that range.
35
- Eg: [1, 5, 3] => cumm_sum = [1, 6, 9]
36
- index 0 covers [1, 1] => covers 1 number
37
- index 1 covers [2, 6] => covers 5 numbers
38
- index 2 covers [7, 9] => covers 3 numbers
39
-
40
- As evident, index 1 has weight = 6 and subsequently covers most numbers as well.
41
- Next we generate a random number in [min_value_cumm_sum, max_value_cumm_sum] range.
42
- Using binary search find the 1st position where it should lie.
43
- */
44
- // ///////////////////////////////////////// SOLUTION 1 ////////////////////////////////////
45
-
46
- class Solution {
47
- private:
48
- // stores the index value of w array
49
- vector<int > idx;
50
- // For generating random numbers in range(0, index_array_size)
51
- random_device rd;
52
- uniform_int_distribution<int > dist;
53
-
54
- public:
55
- Solution (vector<int >& w) {
56
- // Total sum of all the weights
57
- long long sum = accumulate (w.begin (), w.end (), 0 );
58
-
59
- for (int i = 0 ; i < w.size (); i++) {
60
- // Convert the probability score to a natural number, this will be [0, 100]
61
- int prob_score = round ((double )w[i] / sum * 100 );
62
- // If prob_score = 0.00001, then round(prob_score) = 0, so we give min value of 1
63
- // so that atleast one entry for the index is inserted
64
- int prob = max (1 , prob_score);
65
- // For the current index based on the weight, we add that many entries in the
66
- // idx array
67
- vector<int > chance (prob, i);
68
- idx.insert (idx.end (), chance.begin (), chance.end ());
69
- }
70
- // set the random distribution's range
71
- dist = uniform_int_distribution<int >(0 , idx.size () - 1 );
72
- }
73
-
74
- int pickIndex () {
75
- // we randomly generate an index from the index array and then return the index
76
- // value stored there
77
- int index = dist (rd);
78
- return idx[index ];
79
- }
80
- };
81
-
82
-
83
- // ///////////////////////////////////////// SOLUTION 2: Binary Search ///////////////////////////////
84
1
class Solution {
85
- private:
86
- // stores the cummulative sum of w array
87
- vector<int > cumm_sum;
88
- // For generating random numbers in range(0, index_array_size)
89
- random_device rd;
90
- uniform_int_distribution<int > dist;
91
-
92
2
public:
3
+ vector<int > cumW;
93
4
Solution (vector<int >& w) {
94
- long long sum = 0 ;
95
- cumm_sum.resize (w.size (), 0 );
96
-
97
- for (int i = 0 ; i < w.size (); i++) {
98
- sum += w[i];
99
- cumm_sum[i] = sum;
100
- }
101
- // set the random distribution's range: [1, Total_sum_of_w]
102
- dist = uniform_int_distribution<int >(1 , sum);
103
- }
104
-
105
- // Returns the 1st position where the element should be inserted
106
- int binarySearch (int num) {
107
- int low = 0 , high = cumm_sum.size () - 1 ;
108
-
109
- while (low < high) {
110
- int mid = low + (high - low) / 2 ;
111
- if (cumm_sum[mid] == num)
112
- return mid;
113
- else if (cumm_sum[mid] > num)
114
- high = mid;
115
- else
116
- low = mid + 1 ;
117
- }
118
- return high;
5
+ // initialising random seeder
6
+ srand (time (NULL ));
7
+ // populating the cumulative weights vector
8
+ cumW.resize (w.size ());
9
+ cumW[0 ] = w[0 ];
10
+ for (int i = 1 ; i < w.size (); i++) cumW[i] = cumW[i - 1 ] + w[i];
119
11
}
120
12
121
13
int pickIndex () {
122
- // we randomly generate a number from the cumm_sum array and then search the index
123
- // value using binary search. For a w[i] that has more weight, it will cover more numbers
124
- // hence a random number has more chances of falling in that range. We find the 1st position where that number
125
- // can lie.
126
- int random_index = dist (rd);
127
- int index = binarySearch (random_index);
128
- return index ;
14
+ return upper_bound (begin (cumW), end (cumW), rand () % cumW.back ()) - begin (cumW);
129
15
}
130
- };
131
-
132
- /* *
133
- * Your Solution object will be instantiated and called as such:
134
- * Solution* obj = new Solution(w);
135
- * int param_1 = obj->pickIndex();
136
- */
16
+ };
0 commit comments