Random Pick with Weight

题目
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.

分析

一个有趣但是很麻烦的做法是,根据给出的点用Numerical methods得出一个可以approximate这些点的函数。变换这个函数使得这个函数在0到1区间的积分为1, 也就是把它变成一个probability density function.
有了pdf之后可以用Inverse transform sampling方法来sample这个pdf

但是我有这么折腾吗?
没有。

另一个简单的方法是
把w里的n个元素想成是n种水果,水果i的数量为w[i]
假如说w是{1,3,2}
那么把w里的3种水果排开就是这样:

苹果 香蕉 香蕉 香蕉 菠萝 菠萝

一共6个水果。这个时候我们要是从1到6这个区间产生一个随机数,就达到了按weight抽取随机数的目标了。但是我们要返回的答案是Index into array w, 所以要再加一层binary search来检索一下我们产生的随机数落入到哪种水果的范围里。

答案

class Solution {
    int[] cumsum;
    
    Random rand = new Random();
    public Solution(int[] w) {
        if(w.length == 0) return;
        cumsum = new int[w.length];
        cumsum[0] = w[0];
        for(int i = 1; i < w.length; i++) {
            cumsum[i] = w[i] + cumsum[i - 1];
        }
    }

    public int pickIndex() {
        int left = 0, right = cumsum.length;
        int target = rand.nextInt(cumsum[cumsum.length - 1]) + 1;

        // We want to find the index into cumsum array, such that target falls into

        while(left < right) {
            int mid = (left + right) / 2;
            int mid_val = cumsum[mid];

            if(mid_val >= target) {
                right = mid;
            }
            else {
                left = mid + 1;
            }
        }
        return left;
    }
}

你可能感兴趣的:(Random Pick with Weight)