如何根据点列表有效地计算间隔列表?

时间:2015-09-15 00:04:02

标签: algorithm performance haskell time-complexity

所以我有一个间隔列表,让我们说实话,

let intervals = [(1, 12), (2, 5), (3, 24), (7, 8)]

请注意,我只使用括号,因为我将它们存储为成对,间隔实际上是包含的(已关闭)。

我有一个积分清单,

let points = [13, 2, 7, 3, 14]

我正在尝试计算每个时间间隔内的点数,这应该是[Integer],其长度为length intervals

counts == [3, 2, 4, 1]

现在问题实际上intervalspoints 真的长,所以使用O(length intervals * length points)的迭代算法需要永远。因此,我考虑使用某种段树来使其成为O(log (length intervals) * length points)。目前我正在查看包SegmentTree。但是,我对Haskell的有限知识并不足以让我想出一个完整的解决方案。

我理解,如果目标是计算覆盖每个点的间隔数,那么解决方案是直截了当的:

import qualified Data.SegmentTree as S
map (S.countingQuery $ S.fromList intervals) points

但是我无法想出一种反向的方法。对我而言,似乎为了有效地做到这一点,必须使用可变数据结构,这就是打开Pandora Box。

什么是解决方案?

1 个答案:

答案 0 :(得分:3)

如果您可以先对点列表进行排序,则可以非常快速地完成:对于每个间隔,在其下限和上限的点列表中查找索引,然后减去。这些查找采用log(nPoints)时间,并且您正在执行它们的nRanges,因此整体性能将由初始排序(n log n)或查找(m log n)来控制。

这出现在O(log(nPoints) * max(nPoints, nRanges)),这肯定比二次时间更好。这也和我期望的一样好:我没有看到任何聪明的方法来降低线性时间,并且对数因子非常小。

主要的缺点是它需要将整个点列表同时存储在内存中,然而你可以想象存在一个使用较少空间的惰性解决方案。