Leetcode: Non-overlapping Intervals
Given a collection of intervals, find the minimum number of intervals you need to remove to make the rest of the intervals non-overlapping. Note: You may assume the interval's end point is always bigger than its start point. Intervals like [1,2] and [2,3] have borders "touching" but they don't overlap each other. Example 1: Input: [ [1,2], [2,3], [3,4], [1,3] ] Output: 1 Explanation: [1,3] can be removed and the rest of intervals are non-overlapping. Example 2: Input: [ [1,2], [1,2], [1,2] ] Output: 2 Explanation: You need to remove two [1,2] to make the rest of intervals non-overlapping. Example 3: Input: [ [1,2], [2,3] ] Output: 0 Explanation: You don't need to remove any of the intervals since they're already non-overlapping.
Actually, the problem is the same as "Given a collection of intervals, find the maximum number of intervals that are non-overlapping." (the classic Greedy problem: Interval Scheduling). With the solution to that problem, guess how do we get the minimum number of intervals to remove? : )
Sorting Interval.end in ascending order is O(nlogn), then traverse intervals array to get the maximum number of non-overlapping intervals is O(n). Total is O(nlogn).
开始的时候想岔了,以为是要求同一时刻overlap的最多interval数,但仔细想一想就发现不对,应该是non-overlap的interval的最大数目
1. Best solution: sorted by interval end
case 1 add current interval as another non-overlapping interval, case 2 and case 3 all get rid of the current interval
1 /** 2 * Definition for an interval. 3 * public class Interval { 4 * int start; 5 * int end; 6 * Interval() { start = 0; end = 0; } 7 * Interval(int s, int e) { start = s; end = e; } 8 * } 9 */ 10 public class Solution { 11 public int eraseOverlapIntervals(Interval[] intervals) { 12 if (intervals.length == 0) return 0; 13 int nonOverlap = 1; 14 int seq = 0; 15 Arrays.sort(intervals, new Comparator<Interval>() { 16 public int compare(Interval i1, Interval i2) { 17 return i1.end - i2.end; 18 } 19 }); 20 for (int i=1; i<intervals.length; i++) { 21 if (intervals[i].start >= intervals[seq].end) { 22 seq = i; 23 nonOverlap++; 24 } 25 } 26 return intervals.length - nonOverlap; 27 } 28 }
Comparator can also be rewritten as
1 Arrays.sort(intervals, (i1, i2) -> Integer.compare(i1[1], i2[1]));
2. Alternatives(not the best): sort by interval start
case 1 add current interval as another non-overlapping interval, case 2 update the previous non-overlapping interval with the current one, and case 3 get rid of the current interval. So more cases need to be processed than sorted by interval end
1 class Solution { 2 public int eraseOverlapIntervals(int[][] intervals) { 3 if (intervals.length < 1) return 0; 4 int seq = 0; 5 int nonOverlap = 1; 6 7 Arrays.sort(intervals, (i1, i2) -> Integer.compare(i1[0], i2[0])); 8 9 for (int i = 0; i < intervals.length; i ++) { 10 if (intervals[i][0] >= intervals[seq][1]) { 11 seq = i; 12 nonOverlap ++; 13 } 14 else if (intervals[i][1] <= intervals[seq][1]) { 15 seq = i; 16 } 17 } 18 19 return intervals.length - nonOverlap; 20 } 21 }