【发布时间】:2012-02-26 09:03:17
【问题描述】:
将一个项目定义为:
- 唯一的 ID
- 一个值
- 创建时间
- 删除时间
我有两个输入流 - 一个在创建项目时通知我,一个在删除项目时通知我。将已创建但未销毁的项目称为“活着”。
我可以使用堆跟踪所有生物的最大值:
whenCreated(item):
i = heap.size
heap-up(item, heap.size)
heap.size = heap.size + 1
max-value = heap[0]
whenDeleted(item):
ktem = heap[heap.size - 1]
heap.size = heap.size - 1
heap-up(ktem, index[item.id])
heap-down(ktem, index[ktem.id])
max-value = heap[0]
heap-up(item, i):
while (i > 0):
j = floor( (i-1) / 2 )
jtem = heap[j]
if (jtem.value > item.value):
break while
index[jtem.id] = i
heap[i] = heap[i]
i = j
index[item.id] = i
heap[i] = item
heap-down(item, i):
while (2*i + 1 < heap.size):
if (2*i + 1 == heap.size or heap[2*i+1].value > heap[2*i+2].value):
j = 2*i + 1
else
j = 2*i + 2
jtem = heap[j]
if (jtem.value < item.value):
break while
index[jtem.id] = i
heap[i] = heap[i]
i = j
index[item.id] = i
heap[i] = item
如果我有n 项,那么添加或删除一项需要O(log n) 时间。
现在假设这些项目被聚类,使得给定两个项目,a 和 b,|a.value - b.value| < delta ⇒ a 和 b 在同一个集群中。
例如,如果我们有值(1, 2, 3, 4, 7, 8, 11, 13, 14, 15, 16) 和delta = 2,那么集群是(1, 2, 3, 4)、(7, 8)、(11) 和(13, 14, 15, 16)。
我想跟踪包含最大生存值的集群的最小值。我可以通过按顺序从堆中读取值来做到这一点,直到我发现大小大于等于delta 的值之间的差距。但是,这需要O(n) 时间,这似乎相当低效。
是否有 O(log n) 算法来跟踪该集群的最小值?
【问题讨论】:
-
集群是可传递的吗?例如,如果 delta 为 2,那么 1、2、3、4、5 和 6 是否都在同一个集群中?
-
我怀疑你只能用你当前的堆来做到这一点。看来您需要一个单独的数据结构才能有效地做到这一点。不相交的集合会很好,尽管您的集群可以合并然后取消合并,因此您需要允许分离(union-find 不允许)的东西,也就是分区细化。
-
templatetypedef 的答案有效,尽管它似乎很难实现。如果您没有预料到很多临界情况,那么简单的
O(n)解决方案可能是值得的。这意味着如果集群的末端经常变化是罕见的,那么它不是世界末日。您可以通过移动到 BST 并维护单个指针来稍微改进它,然后您的O(n)工作不会在删除时发生,只会在插入时发生,即使这样,如果您期望相对于n的小集群它应该不显眼。
标签: algorithm language-agnostic data-structures stream cluster-analysis