528-random-pick-with-weight
Question
https://leetcode.com/problems/random-pick-with-weight/description/
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.
Note:
- 1 <= w.length <= 10000
- 1 <= w[i] <= 10^5
- pickIndex will be called at most 10000 times.
Example 1:
Input:
["Solution","pickIndex"]
[[[1]],[]]
Output: [null,0]
Example 2:
Input:
["Solution","pickIndex","pickIndex","pickIndex","pickIndex","pickIndex"]
[[[1,3]],[],[],[],[],[]]
Output: [null,0,1,1,1,0]
Explanation of Input Syntax:
The input is two lists: the subroutines called and their arguments. Solution's constructor has one argument, the array w. pickIndex has no arguments. Arguments are always wrapped with a list, even if there aren't any.
Thought Process
- Binary Search
- Since every integer is weighted, we need to get the total sum before we pick a point
- The total sum does not exceed the integer max value, so we can use a int to store the sum
- After creating accumulated sum array, we generate a random point, r, between [0, sum) and perform binary search on this accumulated array
- Time complexity O(n)
- Space complexity O(n)
- TreeMap
- We can leverage the treemap built-in treemap to do similar thing as above
- Save the accumulated sum and its index, we can retrieve the index latter
- Time complexity O(n)
- Space complexity O(n)
- asd
Solution
class Solution {
private int[] presum;
private int n;
private Random rand;
public Solution(int[] w) {
n = w.length;
presum = new int[n];
rand = new Random();
presum[0] = w[0];
for (int i = 1; i < n; i++) presum[i] = presum[i - 1] + w[i];
}
public int pickIndex() {
int r = rand.nextInt(presum[n - 1]) + 1;
int i = Arrays.binarySearch(presum, r);
if (i < 0) i = -(i + 1);
return i;
}
}
/**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(w);
* int param_1 = obj.pickIndex();
*/
class Solution {
private TreeMap<Integer, Integer> map;
private Random rand;
private int total;
public Solution(int[] w) {
map = new TreeMap<>();
total = 0;
rand = new Random();
for (int i = 0; i < w.length; i++) {
total += w[i];
map.put(total, i);
}
}
public int pickIndex() {
int k = map.higherKey(rand.nextInt(total));
return map.get(k);
}
}
/**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(w);
* int param_1 = obj.pickIndex();
*/