单次遍历,带权随机选取问题
2013-10-05 22:49 youxin 阅读(1311) 评论(0) 编辑 收藏 举报在以前的链表单次遍历,随机选取问题中,我们采用水塘抽象方法解决了问题。问题结点带权呢?
问题描述:有一组数量未知的数据,每个元素有非负权重。要求只遍历一次,随机选取其中的一个元素,任何一个元素被选到的概率与其权重成正比。
设元素总数为n,当然在遍历结束前n是未知的。设第i(1 <= i <= n
)个元素的权重为wi(> 0),则权重总和为,也是在遍历结束时才知道的。根据题目要求,第i个元素被选取的概率应该等于
虽然加了个权重,但解法依旧非常简单,在单次遍历,等概率随机选取问题中的RandomSelect函数上稍作修改就得到本问题的解法,依旧是O(n)时间,O(1)辅助空间:
from random import Random def WeightedRandomSelect(rand=None): selection = None totalweight = 0.0 if rand is None: rand = Random() while True: # Outputs the current selection and gets next item (item, weight) = yield selection totalweight += weight if rand.random() * totalweight < weight: selection = item
其中Python的random.random()返回[0, 1)之间的随机小数。
把rand.random()<weight/totalWeigth,则会有好理解一点。(同等概率选取类似,random(1,i)等于1就替换.i分之一,只不过不同概率用权重占比来表示了。)
算法很简单:对于任意的i(1 <= i <= n),按照如下方法给第i个元素分配一个键值key(其中ri是一个0到1之间等概率分布的随机数):

之后,如果要随机选取一个元素,就去key最大的那个;如果要选取m个元素,就取key最大的m个。
真不知道是怎么想出来的这样的方法,不过还是先来关注一下证明的过程。
算法的核心,计算每个元素的随机权重,python版:
更多:
http://www.gocalf.com/blog/weighted-random-selection.html
http://www.gocalf.com/blog/weighted-random-selection-2.html
http://www.cnblogs.com/SuperBrothers/archive/2012/11/13/2768788.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
2012-10-05 jquery 关于ajax的操作