-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathRandomPickWithWeight.java
More file actions
83 lines (68 loc) · 2.57 KB
/
Copy pathRandomPickWithWeight.java
File metadata and controls
83 lines (68 loc) · 2.57 KB
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// Given an array w of positive integers, where w[i] describes the weight of index i,
// write a function pickIndex which randomly picks an index in proportion to its weight.
// See: https://leetcode.com/problems/random-pick-with-weight/
// See: https://leetcode.com/explore/featured/card/june-leetcoding-challenge/539/week-1-june-1st-june-7th/3351/
// See: https://leetcode.com/problems/random-pick-with-weight/discuss/671540/JavaFast-and-Stupid
package leetcode.binary_search;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class RandomPickWithWeight {
/**
* Solution 2 - Binary Search, smarter than Solution 1 but actually not faster.
*/
class Solution {
private final int[] w;
private final Random rnd = new Random();
public Solution(int[] w) {
/*
* Create cumulative weights array .
* @see: https://docs.python.org/3/library/random.html#random.choices
* Intuition: the lenghts of the ranges are proportional of the probability
* so if the range is longer it is more likely to be picked.
*/
for (int i = 1; i < w.length; i++)
w[i] += w[i - 1];
this.w = w;
}
public int pickIndex() {
int target = rnd.nextInt(w[w.length - 1]) + 1;
int left = 0, right = w.length - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (target == w[mid])
return mid;
if (target < w[mid])
right = mid;
else
left = mid + 1;
}
return left;
}
}
/**
* Solution 1 - Simple, stupid but working with high performance.
*/
class Solution1 {
private final List<Integer> list = new ArrayList<>();
private final Random rnd = new Random();
public Solution1(int[] w) {
int sum = 0;
for (int el : w)
sum += el;
for (int i = 0; i < w.length; i++) {
int count = (int) ((w[i] / (sum * 0.1d)) * 100);
count = count == 0 ? 1 : count;
for (int j = 0; j < count; j++)
list.add(i);
}
}
public int pickIndex() {
return list.get(rnd.nextInt(list.size()));
}
}
public static void main(String[] args) {
Solution sln = new RandomPickWithWeight().new Solution(new int[] { 1, 3 });
sln.pickIndex();
}
}