我有一个不相交的间隔和间隔的排序列表,例如[(1,5),(10,15),(20,25)]和(12,27)。所以,(12,27)是间隔 我想将它们合并为一个不相交间隔的排序列表:[(1,5),(10,27)]。
答案 0 :(得分:4)
伪:
list = ...
u = (12,27)
i = 0
newlist = []
while (max(list[i]) < min(u)) //add all intervals before intersection
newlist.add(list[i++])
mini = i
while (min(list[i]) < max(u)) // skip all intersecting intervals
i++
maxi = i
newlist.add((min(list[mini],u),max(list[maxi],u)) // add the new interval
while (i < list.length) // add remaining intervals
newlist.add(list[i++])
return newlist
答案 1 :(得分:0)
你可以用图形模拟你的问题,实际上你的间隔是节点,如果它们有公共部分它们相互连接(例如(12,27)连接到(15,20))现在首先你应该找到连接的组件,然后在每个连接的组件中找到开始的最小值(例如10)和结束的最大值(例如25)。很高兴看到Interval Graphs。
答案 2 :(得分:0)
这是我的非惯用scala解决方案,充满了变量。该解决方案看起来比它应该更长,因为我在列表上的附加和插入实现很差,只支持前置操作。
算法如下:
以下是代码:
object trial {
val intervals1 = List((1, 2), (4, 6), (7, 8), (16, 17)))
val intervals2 = List((1, 5), (10, 15), (20, 25)
val newInterval1 = (11, 12)
val newInterval2 = (12, 27)
// Interval algo test.
val result1 = Merge(intervals1, newInterval1) // result1 : List((1,2), (4,6), (7,8), (11,12), (16,17))
val result2 = Merge(intervals2, newInterval2) // result2 : List[(Int, Int)] = List((1,5), (10,27))
}
object Merge{
def append[T](list: List[T], el: T): List[T] = {
(el :: list.reverse).reverse
}
def insert[T](list: List[T], pos: Int, elem: T): List[T] = {
var newList = List.empty[T]
val reversePos = list.length - pos
list.reverse.zipWithIndex foreach {
case(el, i) if i == reversePos => {
newList = elem :: newList
newList = el :: newList
}
case (el, i) => newList = el :: newList
}
newList
}
def apply(list: List[(Int, Int)], interval: (Int, Int)): List[(Int, Int)] = {
val (min, max) = interval
var newList = List.empty[(Int, Int)]
// Store potentially overlapping stuff.
var overlap = List.empty[(Int, Int)]
// Maintain the position to begin merge.
var posInsert = 0
list.zipWithIndex foreach { case(intervalz, i) =>
if (intervalz._2 < min) {
// Does not overlap but an insert will be after the highest of these.
posInsert = i
newList = append(newList, intervalz)
} else if (intervalz._1 > max) {
// Does not overlap.
newList = append(newList, intervalz)
} else overlap = append(overlap, intervalz)
}
if (overlap isEmpty) {
if (posInsert == 0) newList = interval :: newList
else newList = insert(newList, posInsert + 1, interval)
} else {
// Start of new interval is the lower of the first overlap's start or the interval's start.
val startOfInterval = Math.min(overlap.head._1, min)
// Enf of interval is higher of last overlap's end or interval's end.
val endOfInterval = Math.max(overlap.head._2, max)
// Insert the merged interval after the highest interval smaller than the start of the new internval.
if (posInsert == 0) newList = (startOfInterval, endOfInterval) :: newList
else newList = insert(newList, posInsert + 1, (startOfInterval, endOfInterval))
}
newList
}
}
它通过了这里提到的测试,是O(N)。
EDIT。它的算法版本:
intervals = [....]
newInterval = (12, 27)
newList = []
overlappingList = []
posInsert = 0
i = 0
while (i < intervals.size)
if (intervals[i].max < newInterval.min)
posInsert = i
append(newList, intervals[i])
else if (intervals[i].min > newInterval.max)
append(newList, intervals[i])
else
append(overlappingList, intervals[i])
i++
if (overlap isEmpty)
if (posInsert == 0) prepend(newList, newInterval)
else insert(newList, posInsert + 1, newInterval)
else
start = Min(overlappingList[i].min, newInterval.min)
end = Max(overlappingList[i].max, newInterval.max)
if (posInsert == 0) prepend(newList, newInterval)
else insert(newList, posInsert + 1, new Interval(start, end))
return newList