56. Merge Intervals
Given a collection of intervals, merge all overlapping intervals.
Example 1:
Input: [[1,3],[2,6],[8,10],[15,18]] Output: [[1,6],[8,10],[15,18]] Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].
Example 2:
Input: [[1,4],[4,5]] Output: [[1,5]] Explanation: Intervals [1,4] and [4,5] are considered overlapping.---
Clarifying questions
Are time stamps which are exactly the same considered overlapping - example 2
Intuition
Two approaches
1. Event Scan algorithm
2. Merge intervals
---
Event Scan
Event class - capture point, and isStart boolean for each interval point
Sort with custom comparator
if point values are same Boolean.compare(e2.isStart, e1.isStart) -- put Start points first *
When counter becomes zero -- start to current point is merged interval
---
Merge Intervals
Sorting by start time allows to do Left to Right scan and merge overlapping with easy check
Set prev to 1st element
for i in 2... end
if (current start <= prev end)
merge into prev
else
add prev to ans
prev = current
add prev to ans *
---
Time - O(N Log N) - sorting input array
Space - O(1) - not counting output size
---
Related problems
max-meetings-in-room
---
---
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Solution { | |
class Event { | |
int time; | |
boolean isStart; | |
public Event(int t, boolean s) { | |
time = t; | |
isStart = s; | |
} | |
} | |
public int[][] merge(int[][] intervals) { | |
if (intervals == null || intervals.length == 0) { | |
return new int[][] {}; | |
} | |
List<Event> list = new ArrayList<Event>(); | |
for (int[] interval: intervals) { | |
list.add(new Event(interval[0], true)); | |
list.add(new Event(interval[1], false)); | |
} | |
// Keep start before end to accurate identify overlap on same time | |
Collections.sort(list, (a, b) -> a.time == b.time ? Boolean.compare(b.isStart, a.isStart) : Integer.compare(a.time, b.time)); | |
List<int[]> ret = new ArrayList<int[]>(); | |
for (int i = 0, start = 0, open = 0; i < list.size(); i++) { | |
if (open == 0) { | |
start = list.get(i).time; | |
} | |
if (list.get(i).isStart) { | |
open++; | |
} else { | |
open--; | |
} | |
if (open == 0) { | |
ret.add(new int[] {start, list.get(i).time}); | |
} | |
} | |
int[][] ans = new int[ret.size()][2]; | |
for (int i = 0; i < ret.size(); i++) { | |
ans[i] = ret.get(i); | |
} | |
return ans; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Solution { | |
public int[][] merge(int[][] intervals) { | |
if (intervals == null || intervals.length == 0) { | |
return new int[][] {}; | |
} | |
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0])); | |
int[] prev = intervals[0]; | |
List<int[]> list = new ArrayList<int[]>(); | |
for (int i = 1; i < intervals.length; i++) { | |
if (prev[1] >= intervals[i][0]) { | |
prev[1] = Math.max(prev[1], intervals[i][1]); | |
} else { | |
list.add(new int[] {prev[0], prev[1]}); | |
prev = intervals[i].clone(); | |
} | |
} | |
// make sure to add last entry since the else block isn't executed | |
list.add(prev); | |
int[][] ans = new int[list.size()][2]; | |
for (int i = 0; i < list.size(); i++) { | |
ans[i] = list.get(i); | |
} | |
return ans; | |
} | |
} |