插入已排序且不重叠的区间数组
给定一组不重叠的区间和一个新的区间,在正确的位置插入区间。如果插入导致重叠区间,则合并重叠区间。假设根据开始时间对不重叠的区间集进行排序,以找到正确的插入位置。
先决条件:合并区间
例子:
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)