package com.freetymekiyan.algorithms.level.hard;
import java.util.LinkedList;
import java.util.List;
/**
* Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).
* <p>
* You may assume that the intervals were initially sorted according to their start times.
* <p>
* Example 1:
* Given intervals [1,3],[6,9], insert and merge [2,5] in as [1,5],[6,9].
* <p>
* Example 2:
* Given [1,2],[3,5],[6,7],[8,10],[12,16], insert and merge [4,9] in as [1,2],[3,10],[12,16].
* <p>
* This is because the new interval [4,9] overlaps with [3,5],[6,7],[8,10].
* <p>
* Company Tags: LinkedIn, Google, Facebook
* Tags: Array, Sort
* Similar Problems: (H) Merge Intervals
*/
public class InsertInterval {
/**
* Array. In-place solution.
* Skip the non-overlapping intervals whose end time is before new interval's start.
* For overlapped intervals that start before new interval end.
* | Remove this overlapped interval from list.
* | Merge it with the new interval by: 1. update start to min start times; 2. update end to max end times.
* Add new interval in the position i.
*/
public List<Interval> insert(List<Interval> intervals, Interval newInterval) {
int i = 0;
// Skip the non-overlapping intervals.
while (i < intervals.size() && intervals.get(i).end < newInterval.start) {
i++;
}
while (i < intervals.size() && intervals.get(i).start <= newInterval.end) { // Overlap.
// Remove the overlapped interval.
Interval inter = intervals.remove(i);
// Merge with new interval.
newInterval.start = Math.min(inter.start, newInterval.start);
newInterval.end = Math.min(inter.end, newInterval.end);
}
intervals.add(i, newInterval); // Insert new interval.
return intervals;
}
/**
* Array. Sort. Not in place solution. O(n) Time.
* Make use of intervals are sorted.
* Create a result list of intervals, res.
* Add new interval to res first.
* Go through the given intervals.
* For each interval i, there are 3 situations:
* 1) i and previous interval not overlapping, in front of the new interval.
* 2) No overlap, behind the new interval
* 3) Overlap, merge with the new interval
*/
public List<Interval> insertB(List<Interval> intervals, Interval newInterval) {
List<Interval> res = new LinkedList<>();
res.add(newInterval);
for (Interval i : intervals) {
int start = res.get(res.size() - 1).start; // Last interval.
int end = res.get(res.size() - 1).end;
if (i.end < start) { // i ends before last interval.
res.add(res.size() - 1, i); // Insert it before last interval.
} else if (end < i.start) { // i starts after last interval.
res.add(i); // Append it to last.
} else { // i overlaps with last interval.
start = Math.min(start, i.start);
end = Math.max(end, i.end);
res.set(res.size() - 1, new Interval(start, end));
}
}
return res;
}
public class Interval {
int start;
int end;
Interval() {
start = 0;
end = 0;
}
Interval(int s, int e) {
start = s;
end = e;
}
}
}