【问题标题】:Data structure / algorithms for getting best and worst-scoring object from set用于从集合中获取最佳和最差得分对象的数据结构/算法
【发布时间】:2021-01-02 05:24:39
【问题描述】:

我的算法运行一个循环,其中维护一组对象。在每次迭代中,都会从集合中添加和删除对象。此外,每个对象都有一些“measures”(整数值,可能有几个),可以随时更改。根据这些度量,可以根据度量和迭代次数计算出分数

每当对象的数量超过某个阈值时,我想识别并删除 最低 得分的对象,直到对象的数量再次低于该阈值。即:如果有n 具有阈值t 的对象,如果n>t 则删除n-t 得分最低的对象。 而且,定期我想获得最高-得分

我真的不知道我应该在这里使用什么数据结构来有效地做到这一点。优先级队列并没有真正起作用,因为措施一直在变化,无论如何我想要使用的“分数”可以是这些措施和当前迭代次数的任意复杂函数。显而易见的方法可能是存储关联对象 -> 度量的哈希表,具有分摊的 O(1) 添加/删除/更新操作,但随后找到最低或最高得分的对象将是 O(n) 的元素数量。 n 很容易在短时间内达到数百万,所以这并不理想。这是我能做到的最好的吗?

我意识到这可能不是很简单,但我想知道是否有人对如何最好地实现它有任何建议。

PS:语言是OCaml,但其实没关系。

【问题讨论】:

  • 可能是一个b-tree,每个节点的key就是分数?
  • 但是分数一直在变化,实际上每个分数在每次迭代时都会发生变化,这是由于对迭代次数的依赖。

标签: algorithm


【解决方案1】:

对于这个级别的通用性,最好的办法是有一些东西可以快速访问度量(最好将它们存储在对象中或通过指针,但哈希表也可以)并具有额外的数据结构用于保持对象的有序视图。

每次更新度量时,您都希望刷新分数并更新有序数据结构。平衡 BST 之类的东西可以很好地工作(RB-tree,AVL),并且可以保证 LogN 更新的复杂性。

您也可以保留 min-max heap 来代替 BST。这具有使用较少指针的优点,这应该会降低解决方案的开销。每次更新的复杂度保持为 LogN。

您提到分数取决于迭代次数。这对性能不利,因为它要求每次迭代都更新所有条目。但是,如果您可以隔离影响(例如分数是 g(all_metrics) - f(iteration_number)),以便所有元素受到相同的影响,那么相对顺序应该保持一致,并且您可以跳过每次迭代更新分数。

如果它不是恒定的,但它仍然是孤立的(类似于 f(iteration_number,important_time)),您可以使用平衡 BST 并计算迭代何时将每个元素与其中一个邻居交换,然后将交换时间保持在堆,并且只更新将交换的元素。

如果它根本不是孤立的,那么您将需要在每次迭代时更新所有元素,因此您最好在遍历它们以重新计算分数时跟踪最高值和最低值。这至少会具有 O(NlogK) 的复杂性,其中 K 是您要删除的最低值的数量(希望它非常小,因此它应该表现得几乎像 O(N))。

【讨论】:

  • 谢谢!在对象中存储不起作用,因为有许多循环实例并行运行,引用相同的(不可变的)对象。因此,只有不变量存储在对象中,每个循环都必须将其本地内容保持在自己的状态。至于其余的,它不起作用,因为分数一直在变化,实际上由于对迭代次数 all 的依赖,分数在 all 迭代中会发生变化。我想我会坚持哈希表+线性扫描来找到最低的元素。
  • @andrepd 检查编辑。如果将迭代以简单的方式组合到分数中,您可能仍然可以获得更好的性能。如果您要进行线性扫描,请在更新的同时进行,缓存一致性应该可以提高速度。
猜你喜欢
  • 2018-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多