Given an arraywof positive integers, wherew[i]describes the weight of indexi, write a functionpickIndex which randomly picks an index in proportion to its weight.
The input is two lists: the subroutines called and their arguments. Solution's constructor has one argument, the arrayw.pickIndexhas no arguments. Arguments are always wrapped with a list, even if there aren't any.
Analysis
prefix sum + binary search
用accumlated weight sum代表概率分布,每个区间就模拟了均匀分布的概率。比如
w[] = {2,5,3,4} => wsum[] = {2,7,10,14}
then get random val random.nextInt(14) + 1, idx is in range [1,14]
idx in [1,2] return 0
idx in [3,7] return 1
idx in [8,10] return 2
idx in [11,14] return 3
// Java code to demonstrate the working
// of nextInt(n)
import java.util.*;
public class NextInt2 {
public static void main(String args[])
{
// create random object
Random ran = new Random();
// Print next int value
// Returns number between 0-10
int nxt = ran.nextInt(10);
// Printing the random number between 0 and 10
System.out.println("Random number between 0 and 10 is : " + nxt);
}
}
class Solution {
private int[] accSum;
private int total;
private Random rand;
public Solution(int[] w) {
accSum = new int[w.length];
rand = new Random();
for (int i = 0; i< w.length; i++) {
total += w[i];
accSum[i] = total;
}
}
public int pickIndex() {
int r = rand.nextInt(total) + 1;
int start = 0, end = accSum.length - 1;
while (start <= end) {
int mid = start + (end - start) / 2;
if (accSum[mid] == r) {
return mid;
} else if (accSum[mid] > r) {
end = mid - 1;
} else {
start = mid + 1;
}
}
return start;
}
}
/**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(w);
* int param_1 = obj.pickIndex();
*/