【问题标题】:Fast sampling and update of weighted items (data structure like red-black trees?)加权项的快速采样和更新(像红黑树这样的数据结构?)
【发布时间】:2010-10-15 12:55:41
【问题描述】:

什么是适合这项任务的数据结构?

我有一组 N 个项目。 N 很大。 每个项目都有一个与之相关的正权重值。

我想尽快做以下事情:

内循环:

根据物品的重量对物品进行取样。

[进程...]

更新K个物品的权重,其中K

当我说按重量抽样时,这与统一抽样不同。一个项目的可能性与其重量成正比。因此,如果有两件物品,一件重量为 0.8,一件重量为 0.2,那么它们的可能性分别为 80% 和 20%。

项目数 N 保持不变。权重在有界范围内,例如 [0, 1]。 权重之和并不总是为 1。

一种简单的方法需要 O(n) 个时间步来采样。 有 O(log(n)) 算法吗?

什么是适合这个任务的数据结构? 我认为红黑树是不合适的,因为它们将每个项目视为具有相同的权重。

【问题讨论】:

    标签: algorithm data-structures statistics


    【解决方案1】:

    实际上,您可以为此使用(修改的)RB-trees。此外,任何平衡树(不一定是二叉树)的修改都可以。

    诀窍是在每个节点中存储额外的信息 - 在您的情况下,它可能是以节点为根的子树的总权重,或类似的东西。

    当您更新(即插入/删除)树时,您将遵循您最喜欢的树的算法。当您更改结构时,您只需重新计算节点的总和(这是一个 O(1) 操作,例如旋转和 B 树拆分和连接)。当您更改项目的权重时,您会更新节点祖先的总和。

    采样时,您运行的是修改后的搜索版本。您得到树中所有权重的总和(即根的总和)并生成一个低于此值的正随机数。然后,您运行搜索算法,如果数字(这是您搜索的分位数)小于左节点的总和,则转到左节点。如果你去右边的节点,你从分位数中减去左边的总和。

    这个描述有点乱,但希望对你有帮助。

    【讨论】:

    • 如果使用不精确的表示形式(例如浮点数),更新权重总和可能会遇到困难。
    • 这不是什么大问题 - 最糟糕的情况是结果不准确。
    【解决方案2】:

    我喜欢 jpalecek 的回答。我要补充一点,获取随机数的最简单方法是(1)从统一(0,1)分布生成 u。 (2) 将 u 乘以树中所有权重的总和。

    【讨论】:

      【解决方案3】:

      由于 N 是固定的,您可以使用数组来解决这个问题,比如 v,其中 v[i+1] = v[i] + weight[i], v[1] = weight[0], v[ 0] = 0,对均匀分布在0和权重之和之间的随机数的下界进行二分查找,即log(N)采样。

      K 项的朴素更新是 O(KN),更周到的是 O(N)。

      又被自鸣得意的圈子宠坏了一个面试题:)

      【讨论】:

        【解决方案4】:

        这是我必须为一些蒙特卡罗模拟解决的问题。您可以在下面的链接中看到我当前的“二叉树”。我试图让它非常像 STL。我的树有一个固定的容量,你可以用红黑树的方法来解决这个问题,我已经谈到过尝试。它本质上是 jpacelek 描述的想法的实现。

        该方法在处理不精确的浮点数方面非常稳健,因为它几乎总是求和和比较相同大小的数量,因为它们在树中处于同一级别。

        http://mopssuite.svn.sourceforge.net/viewvc/mopssuite/utils/trunk/include/binary_tree.hpp?view=markup

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-06-03
          • 2021-09-09
          • 2023-03-24
          • 1970-01-01
          • 2011-01-31
          • 2013-02-13
          • 2020-05-30
          • 2011-08-29
          相关资源
          最近更新 更多