AK F.*ing leetcode 流浪计划之加权随机数算法

欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。

本期话题:加权随机数算法

基本问题

给定一个数组A。
要 求 实 现 取 到 数 字 i 的 概 率 为 A [ i ] s u m ( A ) 的 算 法 。 要求实现取到数字i的概率为\frac {A[i]}{sum(A)}的算法。 isum(A)A[i]

问题解析

可以对sum(A)进行分段,然后取个随机数如果落在第0段就取0,依此类推,如果落在第i段,就取i。

每一段可以使用前缀和来表示。

代码模板


class WeightRandom {
    private:
    vector<int> presum;
    int total;
    public:
    WeightRandom(){}
    // 初始
    WeightRandom(vector<int> weights){
        presum.assign(weights.size(), 0);
        presum[0] = weights[0];
        total = weights[0];
        // 构造前缀和
        for(int i=1;i<weights.size();++i) {
            presum[i]=presum[i-1]+weights[i];
            total = presum[i];
        }
    }

    pair<int, int> pick() {
        int n = rand()%total+1;
        int ind = lower_bound( presum.begin(), presum.end(),n)-presum.begin(); // 二分查找区间
        int num = n; // 在区间内具体位置。
        if(ind>0)num -= presum[ind-1];
        return pair<int, int>({ind, num-1});
    }
};

练习一

链接:https://leetcode.cn/problems/random-pick-with-weight/

C++


class WeightRandom {
    private:
    vector<int> presum;
    int total;
    public:
    WeightRandom(){}
    WeightRandom(vector<int> weights){
        presum.assign(weights.size(), 0);
        presum[0] = weights[0];
        total = weights[0];
        for(int i=1;i<weights.size();++i) {
            presum[i]=presum[i-1]+weights[i];
            total = presum[i];
        }
    }

    pair<int, int> pick() {
        int n = rand()%total+1;
        int ind = lower_bound( presum.begin(), presum.end(),n)-presum.begin();
        int num = n;
        if(ind>0)num -= presum[ind-1];
        return pair<int, int>({ind, num-1});
    }
};

class Solution {
    WeightRandom wr;
public:
    Solution(vector<int>& w) {
        wr = WeightRandom(w);
    }
    
    int pickIndex() {
        auto p = wr.pick();
        return p.first;
    }
};

/**
 * Your Solution object will be instantiated and called as such:
 * Solution* obj = new Solution(w);
 * int param_1 = obj->pickIndex();
 */

练习二

链接:https://leetcode.cn/problems/random-point-in-non-overlapping-rectangles/

C++


class WeightRandom {
    private:
    vector<int> presum;
    int total;
    public:
    WeightRandom(){}
    WeightRandom(vector<int> weights){
        presum.assign(weights.size(), 0);
        presum[0] = weights[0];
        total = weights[0];
        for(int i=1;i<weights.size();++i) {
            presum[i]=presum[i-1]+weights[i];
            total = presum[i];
        }
    }

    pair<int, int> pick() {
        int n = rand()%total+1;
        int ind = lower_bound( presum.begin(), presum.end(),n)-presum.begin();
        int num = n;
        if(ind>0)num -= presum[ind-1];
        return pair<int, int>({ind, num-1});
    }
};

class Solution {
    private:
    WeightRandom wr;
    vector<vector<int>> re;
public:
    Solution(vector<vector<int>>& rects) {
        re = rects;
        vector<int> weights;
        for(auto v: rects) {
            weights.push_back((v[2]-v[0]+1)*(v[3]-v[1]+1));
        }
        wr = WeightRandom(weights);
    }
    
    vector<int> pick() {
        auto ans = vector<int>(2);

        auto p = wr.pick();

        int rows = re[p.first][3]-re[p.first][1]+1;
        int cols = re[p.first][2]-re[p.first][0]+1;

        ans[0] = re[p.first][0] + p.second%cols;
        ans[1] = re[p.first][1] + p.second/cols;

        return ans;
    }
};

/**
 * Your Solution object will be instantiated and called as such:
 * Solution* obj = new Solution(rects);
 * vector<int> param_1 = obj->pick();
 */


本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值