实际上,我认为基于散列的方法不适合解决这个问题。最好将其作为列表处理问题来处理。我将在 Haskell 中描述一种方法(这可以翻译成 Perl,只需要稍微多一点的代码)。
一般的方法是记录在任何给定时间有多少元素重叠。为此,我们将从元素的参数列表(开始,结束)对中构建一个“增量”列表 - 运行总数的变化。然后按照它们出现的位置对这些增量进行排序,并组合同时出现的增量。最后,保持增量的运行总和,它等于每个周期开始时重叠元素的数量(每个周期在下一个周期开始时结束)。
完整代码:
import Data.List -- sortBy
import Data.Ord -- comparing
import Data.Function -- `on`
withDelta delta x = (x, delta)
episodeToDelta elements = increases ++ decreases
where increases = map (withDelta 1 . fst) elements
decreases = map (withDelta (-1) . snd) elements
compactDelta::[(Integer,Integer)]->(Integer,Integer)
compactDelta (x:xs) = ((fst x),(sum $ map snd (x:xs)))
adjustTotal (t, delta) ((t1, total1):rest) = (t, total1 + delta):(t1,total1):rest
deltasToRunningTotal = reverse . foldr adjustTotal [(0,0)] . reverse
noZeros = filter (\(_, d) -> d /= 0)
elementsToRunningTotal = deltasToRunningTotal . noZeros . map compactDelta . groupBy ((==) `on` fst) . sortBy (comparing fst) . elementToDelta
sample_elements = [(10,15),(5,9),(13,22),(15,19),(14,16),(3,8),(2,12),(20,22),(23,29)]
> sortBy (comparing fst) sample_elements
[(2,12),(3,8),(5,9),(10,15),(13,22),(14,16),(15,19),(20,22),(23,29)]
> episodesToRunningTotal sample_elements
[(0,0),(2,1),(3,2),(5,3),(8,2),(9,1),(10,2),(12,1),(13,2),(14,3),(16,2),(19,1),(20,2),(22,0),(23,1),(29,0)]