Merge Overlapping Intervals
Given a set of time intervals in any order, merge all overlapping intervals into one and output the result which should have only mutually exclusive intervals. Let the intervals be represented as pairs of integers for simplicity.
For example, let the given set of intervals be {{1,3}, {2,4}, {5,7}, {6,8}}. The intervals {1,3} and {2,4} overlap with each other, so they should be merged and become {1, 4}. Similarly, {5, 7} and {6, 8} should be merged and become {5, 8}
Write a function that produces the set of merged intervals for the given set of intervals.
A simple approach is to start from the first interval and compare it with all other intervals for overlapping, if it overlaps with any other interval, then remove the other interval from the list and merge the other into the first interval. Repeat the same steps for remaining intervals after first. This approach cannot be implemented in better than O(n^2) time.
An efficient approach is to first sort the intervals according to the starting time. Once we have the sorted intervals, we can combine all intervals in a linear traversal. The idea is, in sorted array of intervals, if interval[i] doesn’t overlap with interval[i-1], then interval[i+1] cannot overlap with interval[i-1] because starting time of interval[i+1] must be greater than or equal to interval[i]. Following is the detailed step by step algorithm.
1. Sort the intervals based on increasing order of starting time. 2. Push the first interval on to a stack. 3. For each interval do the following a. If the current interval does not overlap with the stack top, push it. b. If the current interval overlaps with stack top and ending time of current interval is more than that of stack top, update stack top with the ending time of current interval. 4. At the end stack contains the merged intervals.
Below is an implementation of the above approach.
C++
// A C++ program for merging overlapping intervals #include<bits/stdc++.h> using namespace std; // An interval has start time and end time struct Interval { int start, end; }; // Compares two intervals according to their starting time. // This is needed for sorting the intervals using library // function std::sort(). See http://goo.gl/iGspV bool compareInterval(Interval i1, Interval i2) { return (i1.start < i2.start); } // The main function that takes a set of intervals, merges // overlapping intervals and prints the result void mergeIntervals(Interval arr[], int n) { // Test if the given set has at least one interval if (n <= 0) return ; // Create an empty stack of intervals stack<Interval> s; // sort the intervals in increasing order of start time sort(arr, arr+n, compareInterval); // push the first interval to stack s.push(arr[0]); // Start from the next interval and merge if necessary for ( int i = 1 ; i < n; i++) { // get interval from stack top Interval top = s.top(); // if current interval is not overlapping with stack top, // push it to the stack if (top.end < arr[i].start) s.push(arr[i]); // Otherwise update the ending time of top if ending of current // interval is more else if (top.end < arr[i].end) { top.end = arr[i].end; s.pop(); s.push(top); } } // Print contents of stack cout << "\n The Merged Intervals are: " ; while (!s.empty()) { Interval t = s.top(); cout << "[" << t.start << "," << t.end << "] " ; s.pop(); } return ; } // Driver program int main() { Interval arr[] = { {6,8}, {1,9}, {2,4}, {4,7} }; int n = sizeof (arr)/ sizeof (arr[0]); mergeIntervals(arr, n); return 0; } |
Java
// A Java program for merging overlapping intervals import java.util.Arrays; import java.util.Comparator; import java.util.Stack; public class MergeOverlappingIntervals { // The main function that takes a set of intervals, merges // overlapping intervals and prints the result public static void mergeIntervals(Interval arr[]) { // Test if the given set has at least one interval if (arr.length <= 0 ) return ; // Create an empty stack of intervals Stack<Interval> stack= new Stack<>(); // sort the intervals in increasing order of start time Arrays.sort(arr, new Comparator<Interval>(){ public int compare(Interval i1,Interval i2) { return i1.start-i2.start; } }); // push the first interval to stack stack.push(arr[ 0 ]); // Start from the next interval and merge if necessary for ( int i = 1 ; i < arr.length; i++) { // get interval from stack top Interval top = stack.peek(); // if current interval is not overlapping with stack top, // push it to the stack if (top.end < arr[i].start) stack.push(arr[i]); // Otherwise update the ending time of top if ending of current // interval is more else if (top.end < arr[i].end) { top.end = arr[i].end; stack.pop(); stack.push(top); } } // Print contents of stack System.out.print( "The Merged Intervals are: " ); while (!stack.isEmpty()) { Interval t = stack.pop(); System.out.print( "[" +t.start+ "," +t.end+ "] " ); } } public static void main(String args[]) { Interval arr[]= new Interval[ 4 ]; arr[ 0 ]= new Interval( 6 , 8 ); arr[ 1 ]= new Interval( 1 , 9 ); arr[ 2 ]= new Interval( 2 , 4 ); arr[ 3 ]= new Interval( 4 , 7 ); mergeIntervals(arr); } } class Interval { int start,end; Interval( int start, int end) { this .start=start; this .end=end; } } // This code is contributed by Gaurav Tiwari |
C#
// A C# program for merging overlapping intervals using System; using System.Collections; using System.Collections.Generic; public class MergeOverlappingIntervals { // sort the intervals in increasing order of start time class sortHelper : IComparer { int IComparer.Compare( object a, object b) { Interval first = (Interval)a; Interval second = (Interval)b; if (first.start == second.start) { return first.end - second.end; } return first.start - second.start; } } // The main function that takes a set of intervals, merges // overlapping intervals and prints the result public static void mergeIntervals(Interval []arr) { // Test if the given set has at least one interval if (arr.Length <= 0) return ; Array.Sort(arr, new sortHelper()); // Create an empty stack of intervals Stack stack = new Stack(); // Push the first interval to stack stack.Push(arr[0]); // Start from the next interval and merge if necessary for ( int i = 1 ; i < arr.Length; i++) { // get interval from stack top Interval top = (Interval)stack.Peek(); // if current interval is not overlapping with stack top, // Push it to the stack if (top.end < arr[i].start) stack.Push(arr[i]); // Otherwise update the ending time of top if ending of current // interval is more else if (top.end < arr[i].end) { top.end = arr[i].end; stack.Pop(); stack.Push(top); } } // Print contents of stack Console.Write( "The Merged Intervals are: " ); while (stack.Count != 0) { Interval t = (Interval)stack.Pop(); Console.Write( "[" + t.start + "," + t.end + "] " ); } } // Driver code public static void Main() { Interval []arr = new Interval[4]; arr[0] = new Interval(6, 8); arr[1] = new Interval(1, 9); arr[2] = new Interval(2, 4); arr[3] = new Interval(4, 7); mergeIntervals(arr); } } public class Interval { public int start,end; public Interval( int start, int end) { this .start = start; this .end = end; } } // This code is contributed by rutvik_56. |
Output: