Skip to content

Commit 5b67b4b

Browse files
committed
Runtime 97 ms (Top 46.26%) | Memory 40.0 MB (Top 93.61%)
1 parent 2d04896 commit 5b67b4b

File tree

1 file changed

+9
-129
lines changed

1 file changed

+9
-129
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,136 +1,16 @@
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 ///////////////////////////////
841
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-
922
public:
3+
vector<int> cumW;
934
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];
11911
}
12012

12113
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);
12915
}
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

Comments
 (0)