Leetcode 528. 按权重随机选择(中等) 前缀和数组+二分查找左侧边界
labuladong讲解
528. 按权重随机选择(中等)
题目:
思路:
对于[1,7],我们可以将其膨胀为长度为[1,7]的线段,而后产生[1,7]的int随机数x,当x落在1时返回0,当x落在2-7时返回1.实现等概率。
扩展的线段,可以用前缀和数组表示。
查找与x最接近的左侧数值时可以使用二分查找左侧边界实现。
返回时注意left-1,因为presum的id右移了一位
class Solution { public: Solution(vector<int>& w) { int n=w.size(); // 构建前缀和数组,偏移一位留给 preSum[0] presum.resize(n+1); for(int i=1;i<=n;++i){ // preSum[i] = sum(w[0..i-1]) presum[i]=presum[i-1]+w[i-1]; } } int pickIndex() { // 在闭区间 [1, preSum[n - 1]] 中随机选择一个数字 int index=rand()%presum.back()+1; // 获取 target 在前缀和数组 preSum 中的索引 // 搜索左侧边界的二分搜索 int left=1,right=presum.size()-1; while(left<=right){ int mid=left+(right-left)/2; if(presum[mid]<index){ left=mid+1; } else if(presum[mid]>index){ right=mid-1; } else{ right=mid-1; } } // preSum 的索引偏移了一位,还原为权重数组 w 的索引 return left-1; } // 前缀和数组 vector<int> presum; };
联系方式:emhhbmdfbGlhbmcxOTkxQDEyNi5jb20=