在 O(1) 时空复杂度中选择加权任务

Choosing a weighted task in O(1) space-time complexity

提问人:Daniel 提问时间:8/22/2023 更新时间:9/21/2023 访问量:50

问:

假设我有一个任务列表 L。每个任务都由一个整数权重表示,该权重表示任务的重要性。

任务的重要性不会影响其顺序,但会影响其被选中的机会。例如:如果我有 2 个任务 A 和 B,权重分别为 3 和 1,则 A 将有 75% 的机会被选中,而 B 有 25% 的机会被选中。

我怎样才能有一个恒定的时间/空间算法,从任务列表中选择一个随机任务,并考虑其权重?


我目前的解决方案是在 0 和 L 中所有元素的总和之间选择一个随机数。然后我像这样遍历 L

int random = RandomInInterval(0, sumOfL);
foreach(Task T in L){
    random -= T;
    if(random <= 0) return T;
}

这在空间上是恒定的,但在时间上是线性的。有没有办法做一个时间常数的解决方案?

一旦我设置了 L,它就不会改变,所以计算权重之和的复杂性可以忽略不计,因为我只会计算一次。另一方面,我将一直选择任务。

算法 数学 统计 时间复杂度

评论

0赞 Simon Goater 8/22/2023
如果 L 是常数,那么你可以计算一次第 i 个任务的权重之和,然后使用二叉搜索 (O(log(n))) 来查找您的随机任务,而不是线性搜索 (O(n))。

答:

1赞 Matt Timmermans 8/22/2023 #1

恒定时间将需要一个查找表。您可以使用它来优化您已有的程序。

  • 将范围从 0 划分为大小相等的区域,这些区域足够小,以便每个区域与最多 2 个任务的范围重叠。使区域大小小于最小任务范围将确保这一点。sumOfL
  • 创建一个区域数组,为每个区域记录它对应的单个任务,或者两个任务以及它们之间的分界线。

现在,您可以在恒定时间内选择一个区域:

  • 生成一个随机数[0, sumOfL)
  • 除以数组中的区域大小和索引以查找区域
  • 如有必要,根据区域的分界线测试随机数,以确定要选择的两个任务中的哪一个。

评论

0赞 Daniel 8/23/2023
似乎不可能有 O(1) 空间复杂度......
0赞 Chris 9/21/2023 #2

我为此编写了一个库:https://github.com/cdanek/KaimiraWeightedList

如果你想自己卷,你需要花一点。首先阅读别名方法并查看 Keith Schwartz 的解释(这真的很好)。

不幸的是,您将无法获得 O(1) 空间复杂度。O(N),是的,O(1),不,O(1)处理用例(gets)的复杂性是可能的。