528.按权重随机选择

给你一个 下标从 0 开始 的正整数数组 w ,其中 w[i] 代表第 i 个下标的权重。

请你实现一个函数 pickIndex ,它可以 随机地 从范围 [0, w.length - 1] 内(含 0 和 w.length - 1)选出并返回一个下标。选取下标 i 的 概率 为 w[i] / sum(w) 。

例如,对于 w = [1, 3],挑选下标 0 的概率为 1 / (1 + 3) = 0.25 (即,25%),而选取下标 1 的概率为 3 / (1 + 3) = 0.75(即,75%)。
 

示例 1:

输入:
["Solution","pickIndex"]
[[[1]],[]]
输出:
[null,0]
解释:
Solution solution = new Solution([1]);
solution.pickIndex(); // 返回 0,因为数组中只有一个元素,所以唯一的选择是返回下标 0。

思路:前缀和数组+左侧边界的二分查找

当目标元素 target 不存在数组 nums 中时,搜索左侧边界的二分搜索的返回值可以做以下几种解读

1、返回的这个值是 nums 中大于等于 target 的最小元素索引。

2、返回的这个值是 target 应该插入在 nums 中的索引位置。

3、返回的这个值是 nums 中小于 target 的元素个数。

比如在有序数组 nums = [2,3,5,7] 中搜索 target = 4,搜索左边界的二分算法会返回 2,带入均正确。

class Solution {
public:
    vector<int> presum;
    Solution(vector<int>& w) //得到前缀和数组
    {
        presum.resize(w.size()+1,0);
        for(int i=1;i<presum.size();i++)
        {
            presum[i]=presum[i-1]+w[i-1];
        }
    }
    int pickIndex() {
        int n=presum.size();
        int t=(rand()%presum[n-1])+1;
        int left=1,right=n;
        while(left<right)//左侧边界的二分查找
        {
            int mid=(left+right)/2;
            if(presum[mid]==t)
            {
                right=mid;
            }
            else if(presum[mid]>t)
            {
                right=mid;
            }
            else if(presum[mid]<t)
            {
                left=mid+1;
            }
        }
        return left-1;
    }
};

举例:w = [1, 3]

presum=[0,1,4]       1<=target<=4

若target等于2/3/4则在presum中大于等于2/3/4的最小值为4,返回下标2,又因为对应w中的下标1,所以返回1;

若target等于1则在presum中大于等于1的最小值为1,返回下标1,又因为对应w中的下标0,所以返回0;

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值