📜  插入已排序且不重叠的区间数组

📅  最后修改于: 2022-05-13 01:57:49.886000             🧑  作者: Mango

插入已排序且不重叠的区间数组

给定一组不重叠的区间和一个新的区间,在正确的位置插入区间。如果插入导致重叠区间,则合并重叠区间。假设根据开始时间对不重叠的区间集进行排序,以找到正确的插入位置。

先决条件:合并区间

例子:

Input: Set : [1, 3], [6, 9]
        New Interval : [2, 5] 
Output: [1, 5], [6, 9]
The correct position to insert new interval 
[2, 5] is between the two given intervals. 
The resulting set would have been 
[1, 3], [2, 5], [6, 9], but the intervals 
[1, 3], [2, 5] are overlapping. So, they are 
merged together in one interval [1, 5]. 

Input: Set : [1, 2], [3, 5], [6, 7], [8, 10], [12, 16]
        New Interval : [4, 9]
Output: [1, 2], [3, 10], [12, 16]
First the interval is inserted between intervals 
[3, 5] and [6, 7]. Then overlapping intervals are 
merged together in one interval.
推荐:请先在IDE上尝试您的方法,然后查看解决方案

方法:
设要插入的新区间为:[a, b]
案例1: b <(集合中第一个间隔的开始时间)
在这种情况下,只需在集合的开头插入新的间隔。
案例2:(集合中最后一个区间的结束值)< a
在这种情况下,只需在集合的末尾插入新的间隔。
案例3:一个? (第一个间隔的起始值)和 b ? (最后一个区间的结束值)
在这种情况下,新区间与所有区间重叠,即它包含所有区间。所以最终的答案是新的区间本身。
情况4:新的区间不与集合中的任何区间重叠,并且落在集合中的任意两个区间之间
在这种情况下,只需在集合中的正确位置插入间隔。一个示例测试用例是:

Input: Set : [1, 2], [6, 9]
        New interval : [3, 5]
Output: [1, 2], [3, 5], [6, 9]

情况 5:新区间与集合的区间重叠。
在这种情况下,只需将新间隔与重叠间隔合并。要更好地了解如何合并重叠区间,请参阅这篇文章:Merge Overlapping Intervals

上面的示例测试用例示例 2 涵盖了这种情况。

C++
// C++ Code to insert a new interval in set of sorted
// intervals and merge overlapping intervals that are
// formed as a result of insertion.
#include 
 
using namespace std;
 
// Define the structure of interval
struct Interval
{
    int start;
    int end;
    Interval()
        : start(0), end(0)
    {
    }
    Interval(int s, int e)
        : start(s), end(e)
    {
    }
};
 
// A subroutine to check if intervals overlap or not.
bool doesOverlap(Interval a, Interval b)
{
    return (min(a.end, b.end) >= max(a.start, b.start));
}
 
// Function to insert new interval and
// merge overlapping intervals
vector insertNewInterval
(vector& Intervals, Interval newInterval)
{
    vector ans;
    int n = Intervals.size();
 
    // If set is empty then simply insert
    // newInterval and return.
    if (n == 0)
    {
        ans.push_back(newInterval);
        return ans;
    }
 
 
    // Case 1 and Case 2 (new interval to be
    // inserted at corners)
    if (newInterval.end < Intervals[0].start ||
            newInterval.start > Intervals[n - 1].end)
    {
        if (newInterval.end < Intervals[0].start)
            ans.push_back(newInterval);
 
        for (int i = 0; i < n; i++)
            ans.push_back(Intervals[i]);
 
        if (newInterval.start > Intervals[n - 1].end)
            ans.push_back(newInterval);
 
        return ans;
    }
 
    // Case 3 (New interval covers all existing)
    if (newInterval.start <= Intervals[0].start &&
        newInterval.end >= Intervals[n - 1].end)
    {
        ans.push_back(newInterval);
        return ans;
    }
 
    // Case 4 and Case 5
    // These two cases need to check whether
    // intervals overlap or not. For this we
    // can use a subroutine that will perform
    // this function.
    bool overlap = true;
    for (int i = 0; i < n; i++)
    {
        overlap = doesOverlap(Intervals[i], newInterval);
        if (!overlap)
        {
            ans.push_back(Intervals[i]);
 
            // Case 4 : To check if given interval
            // lies between two intervals.
            if (i < n &&
                newInterval.start > Intervals[i].end &&
                newInterval.end < Intervals[i + 1].start)
                ans.push_back(newInterval);
 
            continue;
        }
 
        // Case 5 : Merge Overlapping Intervals.
        // Starting time of new merged interval is
        // minimum of starting time of both
        // overlapping intervals.
        Interval temp;
        temp.start = min(newInterval.start,
                         Intervals[i].start);
 
        // Traverse the set until intervals are
        // overlapping
        while (i < n && overlap)
        {
 
            // Ending time of new merged interval
            // is maximum of ending time both
            // overlapping intervals.
            temp.end = max(newInterval.end,
                           Intervals[i].end);
            if (i == n - 1)
                overlap = false;
            else
                overlap = doesOverlap(Intervals[i + 1],
                                          newInterval);
            i++;
        }
 
        i--;
        ans.push_back(temp);
    }
 
    return ans;
}
 
// Driver code
int main()
{
    vector Intervals;
    Interval newInterval;
 
    newInterval.start = 1;
    newInterval.end = 2;
    Intervals.push_back(newInterval);
    newInterval.start = 3;
    newInterval.end = 5;
    Intervals.push_back(newInterval);
    newInterval.start = 6;
    newInterval.end = 7;
    Intervals.push_back(newInterval);
    newInterval.start = 8;
    newInterval.end = 10;
    Intervals.push_back(newInterval);
    newInterval.start = 12;
    newInterval.end = 16;
    Intervals.push_back(newInterval);
    newInterval.start = 4;
    newInterval.end = 9;
 
    vector ans =
          insertNewInterval(Intervals, newInterval);
 
    for (int i = 0; i < ans.size(); i++)
        cout << ans[i].start << ", "
             << ans[i].end << "\n";
 
    return 0;
}


C++
// C++ program for above approach
#include 
#include 
using namespace std;
 
// Program to merge interval
void mergeInterval2(pair arr[],
                    int n, pair newPair)
{ 
     
    // Create stack of type
    // pair
    stack< pair > stk;
     
    // Pushing first pair
    stk.push(arr[0]);
    
    // Storing the top element
    pair top = stk.top();
   
    // Checking is newPair.first
    // is less than top.second
    if (newPair.first < top.second)
    {
         
        // Pop the top element
        // as it will merge with the
        // previous range
        stk.pop();
       
        // Re-assigning top.first
        top.first = min(top.first,
                          newPair.first);
       
        // Re-assigning top.second
        top.second = max(top.second,
                          newPair.second);
       
        // Push the current interval
        stk.push(top);
    }
    else
    {
         
       // Push the new pair as it does
       // not intersect to first pair
       stk.push(newPair);
    }
 
    // Iterate i from 1 to n - 1
    for (int i = 1; i < n; i++)
    {
         
        // Store the top element of
        // the stack stk
        pair top = stk.top();
       
        // Checking is arr[i].first
        // is less than top.second
        if (arr[i].first < top.second)
        {
             
           
            // Pop the top element
            // as it will merge with the
            // previous range
            stk.pop();
           
            // Re-assigning top.first
            top.first = min(top.first,
                            arr[i].first);
           
            // Re-assigning top.second
            top.second = max(top.second,
                            arr[i].second);
           
            // Push the current interval
            stk.push(top);
        }
         
        else
        {
             
            // Push the new pair as it does
            // not intersect to first pair
            stk.push(arr[i]);
        }
    }
     
    // Storing the final intervals
    stack< pair > finalIntervals;
   
    // Poping the stack elements
    while (stk.empty() != true)
    {
        pair ele =
                       stk.top();
        stk.pop();
        
        // Push ele in finalIntervals
        finalIntervals.push(ele);  
    }
   
     
    // Displaying the final result
    while (finalIntervals.empty() != true)
    {
        pair ele =
                       finalIntervals.top();
        finalIntervals.pop();
       
        cout << ele.first << ", "
             << ele.second << endl;
    }
}
 
// Driver Code
int main()
{
 
    pair arr2[] = {
        { 1, 2 }, { 3, 5 }, { 6, 7 },
                 { 8, 10 }, { 12, 16 }
    };
    pair newPair{ 4, 9 };
    int n2 = sizeof(arr2) / sizeof(arr2[0]);
 
    // Function Call
    mergeInterval2(arr2, n2, newPair);
 
    return 0;
}


Python3
# Python3 program for above approach
 
# Program to merge interval
def mergeInterval2(arr, n, newPair) :
     
    # Create stack of type
    # pair
    stk = []
     
    # Pushing first pair
    stk.append(arr[0])
     
    # Storing the top element
    top = stk[len(stk) - 1]
     
    # Checking is newPair.first
    # is less than top.second
    if (newPair[0] < top[1]) :
         
        # Pop the top element
        # as it will merge with the
        # previous range
        stk.pop()
         
        # Re-assigning top.first
        top[0] = min(top[0], newPair[0])
         
        # Re-assigning top.second
        top[1] = max(top[1], newPair[1])
         
        # Push the current interval
        stk.append(top)
 
    else :
        # Push the new pair as it does
        # not intersect to first pair
        stk.append(newPair)
 
    # Iterate i from 1 to n - 1
    for i in range(1, n) :
         
        # Store the top element of
        # the stack stk
        top = stk[len(stk) - 1]
         
        # Checking is arr[i].first
        # is less than top.second
        if (arr[i][0] < top[1]) :
             
            # Pop the top element
            # as it will merge with the
            # previous range
            stk.pop()
             
            # Re-assigning top.first
            top[0] = min(top[0], arr[i][0])
             
            # Re-assigning top.second
            top[1] = max(top[1], arr[i][1])
             
            # Push the current interval
            stk.append(top)
         
        else :
             
            # Push the new pair as it does
            # not intersect to first pair
            stk.append(arr[i])
     
    # Storing the final intervals
    finalIntervals = []
     
    # Poping the stack elements
    while (len(stk) > 0) :
     
        ele = stk[len(stk) - 1]
        stk.pop()
         
        # Push ele in finalIntervals
        finalIntervals.append(ele)
     
    # Displaying the final result
    while (len(finalIntervals) > 0) :
     
        ele = finalIntervals[len(finalIntervals) - 1]
        finalIntervals.pop()
         
        print(ele[0] , end = ", ")
        print(ele[1])
 
arr2 = [ [ 1, 2 ], [ 3, 5 ], [ 6, 7 ], [ 8, 10 ], [ 12, 16 ] ]
 
newPair = [ 4, 9 ]
n2 = len(arr2)
 
# Function Call
mergeInterval2(arr2, n2, newPair)
 
# This code is contributed by divyesh072019


C#
// C# program for above approach
using System;
using System.Collections;
 
class GFG{
     
// Function to merge interval
static void mergeInterval2(Tuple[] arr,
                    int n, Tuple newPair)
{ 
     
    // Create stack of type
    // pair
    Stack stk = new Stack();
      
    // Pushing first pair
    stk.Push(arr[0]);
     
    // Storing the top element
    Tuple top = (Tuple)stk.Peek();
    
    // Checking is newPair.first
    // is less than top.second
    if (newPair.Item1 < top.Item2)
    {
         
        // Pop the top element
        // as it will merge with the
        // previous range
        stk.Pop();
        
        // Re-assigning top.first and top.second
        top = new Tuple(Math.Min(top.Item1,
                                           newPair.Item1),
                                  Math.Max(top.Item2,
                                           newPair.Item2));
        
        // Push the current interval
        stk.Push(top);
    }
    else
    {
         
        // Push the new pair as it does
        // not intersect to first pair
        stk.Push(newPair);
    }
  
    // Iterate i from 1 to n - 1
    for(int i = 1; i < n; i++)
    {
         
        // Store the top element of
        // the stack stk
        Tuple Top = (Tuple)stk.Peek();
        
        // Checking is arr[i].first
        // is less than top.second
        if (arr[i].Item1 < Top.Item2)
        {
             
            // Pop the top element
            // as it will merge with the
            // previous range
            stk.Pop();
            
            // Re-assigning top.first and top.second
            Top = new Tuple(Math.Min(Top.Item1,
                                               arr[i].Item1),
                                      Math.Max(Top.Item2,
                                               arr[i].Item2));
            
            // Push the current interval
            stk.Push(Top);
        }
        else
        {
             
            // Push the new pair as it does
            // not intersect to first pair
            stk.Push(arr[i]);
        }
    }
      
    // Storing the final intervals
    Stack finalIntervals = new Stack();
    
    // Poping the stack elements
    while (stk.Count != 0)
    {
        Tuple ele = (Tuple)stk.Peek();
        stk.Pop();
         
        // Push ele in finalIntervals
        finalIntervals.Push(ele);  
    }
     
    // Displaying the final result
    while (finalIntervals.Count != 0)
    {
        Tuple ele = (Tuple)finalIntervals.Peek();
                                 
        finalIntervals.Pop();
        
        Console.WriteLine(ele.Item1 + ", " + ele.Item2);
    }
}
 
// Driver Code
static void Main()
{
    Tuple[] arr2 =
    {
        Tuple.Create(1, 2),
        Tuple.Create(3, 5),
        Tuple.Create(6, 7),
        Tuple.Create(8, 10),
        Tuple.Create(12, 16),
    };
     
    Tuple newPair = new Tuple(4, 9);
    int n2 = arr2.Length;
     
    // Function Call
    mergeInterval2(arr2, n2, newPair);
}
}
 
// This code is contributed by divyeshrabadiya07


输出
1, 2
3, 10
12, 16

时间复杂度: O(N)
辅助空间: O(N)

使用堆栈的另一种方法:

我们将在堆栈中推送对,直到它与间隔合并或找到合适的位置来安装它。

下面是上述方法的实现:

C++

// C++ program for above approach
#include 
#include 
using namespace std;
 
// Program to merge interval
void mergeInterval2(pair arr[],
                    int n, pair newPair)
{ 
     
    // Create stack of type
    // pair
    stack< pair > stk;
     
    // Pushing first pair
    stk.push(arr[0]);
    
    // Storing the top element
    pair top = stk.top();
   
    // Checking is newPair.first
    // is less than top.second
    if (newPair.first < top.second)
    {
         
        // Pop the top element
        // as it will merge with the
        // previous range
        stk.pop();
       
        // Re-assigning top.first
        top.first = min(top.first,
                          newPair.first);
       
        // Re-assigning top.second
        top.second = max(top.second,
                          newPair.second);
       
        // Push the current interval
        stk.push(top);
    }
    else
    {
         
       // Push the new pair as it does
       // not intersect to first pair
       stk.push(newPair);
    }
 
    // Iterate i from 1 to n - 1
    for (int i = 1; i < n; i++)
    {
         
        // Store the top element of
        // the stack stk
        pair top = stk.top();
       
        // Checking is arr[i].first
        // is less than top.second
        if (arr[i].first < top.second)
        {
             
           
            // Pop the top element
            // as it will merge with the
            // previous range
            stk.pop();
           
            // Re-assigning top.first
            top.first = min(top.first,
                            arr[i].first);
           
            // Re-assigning top.second
            top.second = max(top.second,
                            arr[i].second);
           
            // Push the current interval
            stk.push(top);
        }
         
        else
        {
             
            // Push the new pair as it does
            // not intersect to first pair
            stk.push(arr[i]);
        }
    }
     
    // Storing the final intervals
    stack< pair > finalIntervals;
   
    // Poping the stack elements
    while (stk.empty() != true)
    {
        pair ele =
                       stk.top();
        stk.pop();
        
        // Push ele in finalIntervals
        finalIntervals.push(ele);  
    }
   
     
    // Displaying the final result
    while (finalIntervals.empty() != true)
    {
        pair ele =
                       finalIntervals.top();
        finalIntervals.pop();
       
        cout << ele.first << ", "
             << ele.second << endl;
    }
}
 
// Driver Code
int main()
{
 
    pair arr2[] = {
        { 1, 2 }, { 3, 5 }, { 6, 7 },
                 { 8, 10 }, { 12, 16 }
    };
    pair newPair{ 4, 9 };
    int n2 = sizeof(arr2) / sizeof(arr2[0]);
 
    // Function Call
    mergeInterval2(arr2, n2, newPair);
 
    return 0;
}

Python3

# Python3 program for above approach
 
# Program to merge interval
def mergeInterval2(arr, n, newPair) :
     
    # Create stack of type
    # pair
    stk = []
     
    # Pushing first pair
    stk.append(arr[0])
     
    # Storing the top element
    top = stk[len(stk) - 1]
     
    # Checking is newPair.first
    # is less than top.second
    if (newPair[0] < top[1]) :
         
        # Pop the top element
        # as it will merge with the
        # previous range
        stk.pop()
         
        # Re-assigning top.first
        top[0] = min(top[0], newPair[0])
         
        # Re-assigning top.second
        top[1] = max(top[1], newPair[1])
         
        # Push the current interval
        stk.append(top)
 
    else :
        # Push the new pair as it does
        # not intersect to first pair
        stk.append(newPair)
 
    # Iterate i from 1 to n - 1
    for i in range(1, n) :
         
        # Store the top element of
        # the stack stk
        top = stk[len(stk) - 1]
         
        # Checking is arr[i].first
        # is less than top.second
        if (arr[i][0] < top[1]) :
             
            # Pop the top element
            # as it will merge with the
            # previous range
            stk.pop()
             
            # Re-assigning top.first
            top[0] = min(top[0], arr[i][0])
             
            # Re-assigning top.second
            top[1] = max(top[1], arr[i][1])
             
            # Push the current interval
            stk.append(top)
         
        else :
             
            # Push the new pair as it does
            # not intersect to first pair
            stk.append(arr[i])
     
    # Storing the final intervals
    finalIntervals = []
     
    # Poping the stack elements
    while (len(stk) > 0) :
     
        ele = stk[len(stk) - 1]
        stk.pop()
         
        # Push ele in finalIntervals
        finalIntervals.append(ele)
     
    # Displaying the final result
    while (len(finalIntervals) > 0) :
     
        ele = finalIntervals[len(finalIntervals) - 1]
        finalIntervals.pop()
         
        print(ele[0] , end = ", ")
        print(ele[1])
 
arr2 = [ [ 1, 2 ], [ 3, 5 ], [ 6, 7 ], [ 8, 10 ], [ 12, 16 ] ]
 
newPair = [ 4, 9 ]
n2 = len(arr2)
 
# Function Call
mergeInterval2(arr2, n2, newPair)
 
# This code is contributed by divyesh072019

C#

// C# program for above approach
using System;
using System.Collections;
 
class GFG{
     
// Function to merge interval
static void mergeInterval2(Tuple[] arr,
                    int n, Tuple newPair)
{ 
     
    // Create stack of type
    // pair
    Stack stk = new Stack();
      
    // Pushing first pair
    stk.Push(arr[0]);
     
    // Storing the top element
    Tuple top = (Tuple)stk.Peek();
    
    // Checking is newPair.first
    // is less than top.second
    if (newPair.Item1 < top.Item2)
    {
         
        // Pop the top element
        // as it will merge with the
        // previous range
        stk.Pop();
        
        // Re-assigning top.first and top.second
        top = new Tuple(Math.Min(top.Item1,
                                           newPair.Item1),
                                  Math.Max(top.Item2,
                                           newPair.Item2));
        
        // Push the current interval
        stk.Push(top);
    }
    else
    {
         
        // Push the new pair as it does
        // not intersect to first pair
        stk.Push(newPair);
    }
  
    // Iterate i from 1 to n - 1
    for(int i = 1; i < n; i++)
    {
         
        // Store the top element of
        // the stack stk
        Tuple Top = (Tuple)stk.Peek();
        
        // Checking is arr[i].first
        // is less than top.second
        if (arr[i].Item1 < Top.Item2)
        {
             
            // Pop the top element
            // as it will merge with the
            // previous range
            stk.Pop();
            
            // Re-assigning top.first and top.second
            Top = new Tuple(Math.Min(Top.Item1,
                                               arr[i].Item1),
                                      Math.Max(Top.Item2,
                                               arr[i].Item2));
            
            // Push the current interval
            stk.Push(Top);
        }
        else
        {
             
            // Push the new pair as it does
            // not intersect to first pair
            stk.Push(arr[i]);
        }
    }
      
    // Storing the final intervals
    Stack finalIntervals = new Stack();
    
    // Poping the stack elements
    while (stk.Count != 0)
    {
        Tuple ele = (Tuple)stk.Peek();
        stk.Pop();
         
        // Push ele in finalIntervals
        finalIntervals.Push(ele);  
    }
     
    // Displaying the final result
    while (finalIntervals.Count != 0)
    {
        Tuple ele = (Tuple)finalIntervals.Peek();
                                 
        finalIntervals.Pop();
        
        Console.WriteLine(ele.Item1 + ", " + ele.Item2);
    }
}
 
// Driver Code
static void Main()
{
    Tuple[] arr2 =
    {
        Tuple.Create(1, 2),
        Tuple.Create(3, 5),
        Tuple.Create(6, 7),
        Tuple.Create(8, 10),
        Tuple.Create(12, 16),
    };
     
    Tuple newPair = new Tuple(4, 9);
    int n2 = arr2.Length;
     
    // Function Call
    mergeInterval2(arr2, n2, newPair);
}
}
 
// This code is contributed by divyeshrabadiya07
输出
1, 2
3, 10
12, 16

时间复杂度: O(N)
辅助空间: O(N)