Insert in sorted and non-overlapping interval array

30 Jun, 2022
Given a set of non-overlapping intervals and a new interval, insert the interval at correct position. If the insertion results in overlapping intervals, then merge the overlapping intervals. Assume that the set of non-overlapping intervals is sorted on the basis of start time, to find correct position of insertion.
Prerequisite: Merge the intervals
Examples: 
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.
Method 1:  Analyzing all CasesApproach: Let the new interval to be inserted is : [a, b] Case 1 : b < (starting time of first interval in set) In this case simply insert new interval at the beginning of the set.Case 2 : (ending value of last interval in set) < a In this case simply insert new interval at the end of the set.Case 3 : a ? (starting value of first interval) and b ? (ending value of last interval) In this case the new interval overlaps with all the intervals, i.e., it contains all the intervals. So the final answer is the new interval itself.Case 4 : The new interval does not overlap with any interval in the set and falls between any two intervals in the set In this case simply insert the interval in the correct position in the set. A sample test case for this is : 
Input: Set : [1, 2], [6, 9]
        New interval : [3, 5]
Output: [1, 2], [3, 5], [6, 9]
Case 5 : The new interval overlaps with the interval(s) of the set. In this case simply merge the new interval with overlapping intervals. To have a better understanding of how to merge overlapping intervals, refer this post : Merge Overlapping Intervals 
Example 2 of sample test cases above cover this case. 
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 <bits/stdc++.h> using namespace std; // Define the structure of intervalstruct 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 intervalsvector<Interval> insertNewInterval(vector<Interval>& Intervals, Interval newInterval){    vector<Interval> 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 codeint main(){    vector<Interval> 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<Interval> ans =          insertNewInterval(Intervals, newInterval);     for (int i = 0; i < ans.size(); i++)        cout << ans[i].start << ", "             << ans[i].end << "\n";     return 0;}
1, 2
3, 10
12, 16
Time Complexity: O(N) Auxiliary Space: O(N) 
Method 2: Using merge intervals
Append the given interval to the given list of the intervals.Now it becomes the same old merge intervals problem. To have a better understanding of how to merge overlapping intervals, refer this post : Merge Overlapping Intervals Use the merge intervals function.
Append the given interval to the given list of the intervals.
Now it becomes the same old merge intervals problem. To have a better understanding of how to merge overlapping intervals, refer this post : Merge Overlapping Intervals 
Use the merge intervals function.
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 <bits/stdc++.h> using namespace std; // Define the structure of intervalstruct Interval{    int s, e;}; // A subroutine to check if intervals overlap or not.bool mycomp(Interval a, Interval b) { return a.s < b.s; } // merge overlapping intervalsvoid insertNewInterval(vector<Interval>& Intervals, Interval newInterval){    vector<Interval> ans;    int n = Intervals.size();    Intervals.push_back(newInterval); //Insert the new interval into Intervals    sort(Intervals.begin(), Intervals.end(), mycomp);      int index = 0;    // Traverse all input Intervals    for (int i = 1; i <=n; i++) {        // If this is not first Interval and overlaps        // with the previous one        if (Intervals[index].e >= Intervals[i].s) {            // Merge previous and current Intervals            Intervals[index].e = max(Intervals[index].e, Intervals[i].e);        }        else {            index++;            Intervals[index] = Intervals[i];        }    }       for (int i = 0; i <= index; i++)        cout  << Intervals[i].s << ", " << Intervals[i].e << "\n";} // Driver codeint main(){    vector<Interval> Intervals;    Interval newInterval;     newInterval.s = 1;    newInterval.e = 2;    Intervals.push_back(newInterval);    newInterval.s = 3;    newInterval.e = 5;    Intervals.push_back(newInterval);    newInterval.s = 6;    newInterval.e = 7;    Intervals.push_back(newInterval);    newInterval.s = 8;    newInterval.e = 10;    Intervals.push_back(newInterval);    newInterval.s = 12;    newInterval.e = 16;    Intervals.push_back(newInterval);    newInterval.s = 4;    newInterval.e = 9;     insertNewInterval(Intervals, newInterval);     return 0;}
1, 2
3, 10
12, 16
Time Complexity: O(nlogn) Auxiliary Space: O(1)
Method 3: Another Approach Using Stack:
We will be pushing pairs in the stack until it merges with the intervals or finds a suitable place for fitting it.
Below is the implementation of the above approach:
C++
Python3
C#
// C++ program for above approach#include <iostream>#include <stack>using namespace std; // Program to merge intervalvoid mergeInterval2(pair<int, int> arr[],                    int n, pair<int,                               int> newPair){          // Create stack of type    // pair<int, int>    stack< pair<int, int> > stk;         // Pushing first pair    stk.push(arr[0]);        // Storing the top element    pair<int, int> 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<int, int> 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<int,int> > finalIntervals;       // Popping the stack elements    while (stk.empty() != true)    {        pair<int, int> ele =                       stk.top();        stk.pop();                // Push ele in finalIntervals        finalIntervals.push(ele);      }            // Displaying the final result    while (finalIntervals.empty() != true)    {        pair<int, int> ele =                       finalIntervals.top();        finalIntervals.pop();               cout << ele.first << ", "             << ele.second << endl;    }} // Driver Codeint main(){     pair<int, int> arr2[] = {        { 1, 2 }, { 3, 5 }, { 6, 7 },                 { 8, 10 }, { 12, 16 }    };    pair<int, int> newPair{ 4, 9 };    int n2 = sizeof(arr2) / sizeof(arr2[0]);     // Function Call    mergeInterval2(arr2, n2, newPair);     return 0;}
# Python3 program for above approach # Program to merge intervaldef mergeInterval2(arr, n, newPair) :         # Create stack of type    # pair<int, int>    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 = []         # Popping 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 CallmergeInterval2(arr2, n2, newPair) # This code is contributed by divyesh072019
// C# program for above approachusing System;using System.Collections; class GFG{     // Function to merge intervalstatic void mergeInterval2(Tuple<int, int>[] arr,                    int n, Tuple<int, int> newPair){          // Create stack of type    // pair<int, int>    Stack stk = new Stack();          // Pushing first pair    stk.Push(arr[0]);         // Storing the top element    Tuple<int,          int> top = (Tuple<int,                            int>)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<int, int>(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<int,              int> Top = (Tuple<int,                                int>)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<int, int>(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();        // Popping the stack elements    while (stk.Count != 0)    {        Tuple<int,              int> ele = (Tuple<int,                                int>)stk.Peek();        stk.Pop();                 // Push ele in finalIntervals        finalIntervals.Push(ele);      }         // Displaying the final result    while (finalIntervals.Count != 0)    {        Tuple<int,              int> ele = (Tuple<int,                                int>)finalIntervals.Peek();                                         finalIntervals.Pop();                Console.WriteLine(ele.Item1 + ", " + ele.Item2);    }} // Driver Codestatic void Main(){    Tuple<int, int>[] arr2 =    {        Tuple.Create(1, 2),        Tuple.Create(3, 5),        Tuple.Create(6, 7),        Tuple.Create(8, 10),        Tuple.Create(12, 16),    };         Tuple<int,          int> newPair = new Tuple<int,                                   int>(4, 9);    int n2 = arr2.Length;         // Function Call    mergeInterval2(arr2, n2, newPair);}} // This code is contributed by divyeshrabadiya07
1, 2
3, 10
12, 16
Time Complexity: O(N) Auxiliary Space: O(N) 
riajaiswal
divyesh072019
divyeshrabadiya07
surinderdawra388
isha307
cpp-vector
Arrays
Arrays
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.