Given a set of closed intervals, find the smallest set of numbers that covers all the intervals. If there are multiple smallest sets, return any of them.
For example, given the intervals [0, 3], [2, 6], [3, 4], [6, 9]
, one set of numbers that covers all these intervals is {3, 6}
.
This problem bcomes clearer if we sort the intervals by the starting points. For example, intervals [[10, 20], [1, 6], [3, 8], [7, 12]]
should become [[1, 6], [3, 8], [7, 12], [10, 20]]
.
Now, to cover the first interval, [1, 6]
, we must pick a number in between the interval. However, if the next interval intersects, then we can solve an easier interval problem of picking a point between their intersection. This would let us use 1 less point to cover the intervals. Then, we can look at the third intersection and so forth to find the first k
intervals which all intersect. Once we find an interval that doesn't intersect, we can pick a point in the intersection of all the previous intervals. Then we repeat the process starting from the current interval.
In the above example, the intersection of [[1, 6], [3, 8]]
is [3, 6]
while the intersection of [7, 12], [10, 20]
is [10, 12]
.
public class SmallestSetToCoverInterval { class Interval { int start, end; Interval(int start, int end) { this.start = start; this.end = end; } public int getStart() { return start; } public int getEnd() { return end; } public void setStart(int start) { this.start = start; } public void setEnd(int end) { this.end = end; } } public Set<Integer> smallestSetToCoverInterval(Interval[] intervals) { Arrays.sort(intervals, Comparator.comparingInt(Interval::getStart)); Set<Integer> set = new HashSet<>(); int i = 0; while (i < intervals.length) { Interval interval = intervals[i]; while (i < intervals.length && intersect(interval, intervals[i])) { interval.setStart(Math.max(interval.start, intervals[i].start)); interval.setEnd(Math.min(interval.end, intervals[i].end)); i++; } set.add(interval.end); } return set; } private boolean intersect(Interval i1, Interval i2){ return !(i1.start > i2.end || i2.start > i1.end); } }