Algorithm 在不相交区间的排序列表中插入区间

Algorithm 在不相交区间的排序列表中插入区间,algorithm,Algorithm,我有一个不相交区间的排序列表和一个区间,例如[(1,5),(10,15),(20,25)]和(12,27)。所以,(12,27)是间隔 我想把它们合并成一个不相交区间的排序列表:[(1,5)、(10,27)] 伪: list = ... u = (12,27) i = 0 newlist = [] while (max(list[i]) < min(u)) //add all intervals before intersection newlist.add(list[i++])

我有一个不相交区间的排序列表和一个区间,例如[(1,5),(10,15),(20,25)]和(12,27)。所以,(12,27)是间隔 我想把它们合并成一个不相交区间的排序列表:[(1,5)、(10,27)]

伪:

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
list=。。。
u=(12,27)
i=0
新列表=[]
while(max(list[i])
伪:

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
list=。。。
u=(12,27)
i=0
新列表=[]
while(max(list[i])
您可以使用图形对问题进行建模,事实上,您的间隔是节点,如果它们有公共部分(例如(12,27)连接到(15,20)),则它们彼此连接。现在,您应该首先查找连接的组件,然后在每个连接的组件中查找开始的最小值(例如10)和最大值end(例如25)。很高兴看到。

您可以用图形建模您的问题,事实上,您的间隔是节点,如果它们有公共部分(例如(12,27)连接到(15,20)),则它们相互连接现在,您应该首先找到连接的组件,然后在每个连接的组件中找到开始的最小值(例如10)和结束的最大值(例如25)。很高兴看到。

这是我的非惯用scala解决方案,其中充满了变量。该解决方案看起来比它应该的要长,因为我的append和insert-on-List的实现很差,只支持prepend操作

算法如下:

  • 扫描以将间隔列表分为两个列表,一个是与新间隔不重叠的列表,另一个是与新间隔重叠的列表。非重叠间隔是指完全在新间隔之后或之前开始的列表。此外,如果要插入新间隔,则它将位于低于新间隔的最高间隔之后。在此阶段,我们有重叠间隔列表和非重叠间隔列表
  • 如果没有重叠,则新间隔可能早于所有给定间隔或在所有间隔之后或在两个间隔之间(仍然没有重叠)
  • 如果存在重叠,则将重叠间隔与新间隔合并。重叠间隔的开始时间为min(新间隔的开始时间,最小重叠间隔的开始时间)。我们可以类似地计算结束时间。现在将重叠间隔插入先前计算的位置
  • 代码如下:

    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
      }
    }
    
    目标审判{
    val intervals1=列表((1,2)、(4,6)、(7,8)、(16,17)))
    val intervals2=列表((1,5)、(10,15)、(20,25)
    val newInterval1=(11,12)
    val newInterval2=(12,27)
    //间隔算法测试。
    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))
    }
    对象合并{
    def append[T](列表:列表[T],el:T):列表[T]={
    (el::list.reverse)。反向
    }
    def insert[T](列表:列表[T],位置:Int,元素:T):列表[T]={
    var newList=List.empty[T]
    val reversePos=list.length-pos
    list.reverse.zipWithIndex foreach{
    如果i==reversePos=>{
    newList=elem::newList
    newList=el::newList
    }
    案例(el,i)=>newList=el::newList
    }
    新名单
    }
    定义应用(列表:列表[(Int,Int)],间隔:(Int,Int)):列表[(Int,Int)]={
    val(最小值,最大值)=间隔
    var newList=List.empty[(Int,Int)]
    //存储可能重叠的内容。
    var overlap=List.empty[(Int,Int)]
    //保持开始合并的位置。
    var posInsert=0
    list.zipWithIndex foreach{case(intervalz,i)=>
    如果(间隔2<分钟){
    //不重叠,但插入将位于其中的最高位置之后。
    posInsert=i
    newList=append(newList,intervalz)
    }否则如果(间隔时间>最大值){
    //不重叠。
    newList=append(newList,intervalz)
    }else重叠=附加(重叠,间隔)
    }
    如果(重叠为空){
    如果(posInsert==0)newList=interval::newList
    else newList=insert(newList,posInsert+1,interval)
    }否则{
    //新间隔的起点是第一个重叠的起点或间隔的起点中的较低者。
    val startOfInterval=Math.min(重叠头1,min)
    //区间的Enf高于最后一个重叠的终点或区间的终点。
    val endOfInterval=数学最大值(重叠头2,最大值)
    //在小于新interval开头的最高间隔之后插入合并间隔。
    如果(posInsert==0)newList=(startOfInterval,endOfInterval)::newList
    else newList=insert(newList,posInsert+1,(startOfInterval,endOfInterval))
    }
    新名单
    }
    }
    
    它通过了这里提到的测试,是O(N)

    编辑。它的algo版本:

    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
    
    interval=[…]
    新间隔=(12,27)
    新列表=[]
    重叠列表=[]
    posInsert=0
    i=0
    while(inewInterval.max)
    追加(新列表,间隔[i])
    其他的
    追加(重叠列表,间隔[i])
    我++
    如果(重叠为空)
    if(posInsert==0)前置(newList,newInterval)
    else插入(newList,posInsert+1,newInterval)
    其他的
    开始=最小值(重叠列表