In this blogpost, I take a stab at learning questions related to merge intervals. Let's jump right in!
Why are merge intervals important?
Having an understanding of how to merge intervals can be pretty practical in real life too! Some use cases are - you are trying to figure out how many meeting rooms to build in your new office location based on the meeting habits of your employees, find a number of rooms that can be vacant in a hotel based on checkout times, etc.
Problem Statement
Given an array of intervals
where intervals[i] = [start<sub>i</sub>, end<sub>i</sub>]
, merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input.
Example:
Input: intervals = [[1,3],[2,6],[8,10],[15,18]] Output: [[1,6],[8,10],[15,18]]
Understanding the problem statement
Here they give the input in the form of a 2D array of the format intervals[i][2] where the start is intervals[i][0]
and end is intervals[i][1]
Notice that they don't mention if the input is the sorted or not. In questions like merge intervals, it can be helpful to sort the input by start indices. Why do you think so? Let's consider the case of meeting intervals. If you were trying to book a room for a meeting and say you have two lists of booked timings:
list_1
= [12pm - 2pm, 10 am - 10:30 am, 6:30 am - 9 am, 1 pm - 1:30 pm, 7 am - 6 pm]
list_2
= [ 6:30 am - 9 am, 7 am - 8 am, 10 am - 10:30 am, 12pm - 2pm, 1 pm - 1:30 pm]
Which list gives you a better idea of what times the room is going to be occupied? Clearly, the second one. This is why it is helpful to sort the input when intervals might indicate something sequential.
Considering edge cases
Negative input?
Is the input sorted? nope - we need to sort it
Empty input?
Approach
Since there are overlapping intervals, we need to figure out 2 things to add to the result - intervals that are not overlapping and intervals that need to be merged into one interval.
We first sort the intervals based on the start time. This helps us ensure that we have a sequential array that makes it easy to compare the overlap of elements.
So let's take this example that is now sorted - list
\= [ 6:30 am - 9 am, 7 am - 8 am, 10 am - 10:30 am, 12pm - 2pm, 1 pm - 1:30 pm]
For this case, we can loop through all intervals one by one and initialize a temporary interval that stores the start of each interval.
Now how can you say that an interval is overlapping?
Let's take list[0] = 6:30 am - 9 am
and list[1] = 7am - 8 am
. Here you notice that the list[1]'s start time is lesser than the end time of list[0]. So to generalize this, we can write the condition as list[i+1][start] <= list[i][end]
Now we continue checking for this condition until it is broken. This gives us the merged interval that we can put into our result. We continue doing the same until we finish iterating through the entire list of intervals.
Code Solution
class Solution {
public int[][] merge(int[][] intervals) {
int start = 0; int end = 1;
List<int[]> result = new ArrayList<>();
//sort the intervals by start time
Arrays.sort(intervals, (a,b) -> Integer.compare(a[0],b[0]));
for(int i = 0; i < intervals.length; i++){
int[] temp = new int[2];
temp[start] = intervals[i][start]; //initialize the start for temp
temp[end] = intervals[i][end];
//if there is an overlapping element, modify its end time
//to reflect it
while(i+1 < intervals.length && intervals[i+1][start] <= temp[end]){
temp[end] = Math.max(temp[end], intervals[i+1][end]);
i++;
}
result.add(temp);
}
return result.toArray(new int[][]{});
}
}