【问题标题】:Weighted random numbers V2 (Dynamic case)加权随机数 V2(动态情况)
【发布时间】:2026-01-19 22:30:01
【问题描述】:

此问题是链接下方问题的延伸。

Weighted random numbers

我的问题是对加权随机数进行抽样,附加条件是每个元素的权重经常动态变化。

编辑 假设有 N 个元素需要选择不同的权重。

对于静态权重,Walker 的别名方法需要 O(N) 时间来设置别名,但采样成本为 O(1),因此它是实现我目标的最佳方法之一。

而二分查找法也需要O(N)来做累积数组,采样成本是log(N)

但是在我的情况下,由于权重经常更改,因此修改权重的时间复杂度也很重要。

所以我想知道现有的库或算法的时间复杂度对于修改数据结构和采样都小于 O(N)。

编辑当我阅读 cmets 时,我意识到我需要施加额外的条件。每个修改阶段,只修改少数(大部分是两个)权重,这些修改也不会改变权重的总和(归一化条件)。

如果有解决方案,我也想知道当权重也是实数时是否可以使用。

【问题讨论】:

  • N为元素个数/在链接中,N =3 { 1, 2, 3}
  • 好的,我明白了。大概整体复杂性取决于您需要多久修改一次权重;您是说每次迭代都需要这样做吗?
  • 是的,在我的问题中,权重由先前采样的元素更改。所以我需要在每次迭代时修改权重。
  • 你是每次迭代都修改所有的权重(在这种情况下你可能不走运),还是只修改一些?
  • 如果只有 O(1) 主要只是两个权重被修改怎么办?如果修改不改变总重量,也不需要标准化?

标签: c++ c random sampling


【解决方案1】:

我也面临同样的问题。我将描述我目前解决它的计划,但如果有任何其他建议和/或实施指南,我将不胜感激。

我目前的计划是调整动态订单统计算法,如 Cormen/Leiserson/Rivest 的“算法简介”的 14.1 部分所述。您将元素放入平衡的二叉树中,例如红黑树,权重作为键。您对树进行扩充,以便每个节点将权重总和存储在其子树中。然后根存储整个树中的权重总和,例如S。子树总和可以在树操作期间以与动态顺序统计的子树大小相同的方式更新。做加权抽样,你对[0..S]中的一个数进行统一抽样,比如说x;然后向下搜索节点N,使得在顺序遍历中N之前的节点的权重之和为<x,但总和加上N的权重为>x——类似于用于动态订单统计的 OS-Select 操作。

【讨论】: