Given a list of intervals, find a subset of it that covers the longest length and doesn’t overlap with each other
Solution credit to my brother. Great Solution
- The dp will maintain an int array dp[], dp[i] is the max covered length of any subset of non-overlapped intervals that contains itself (the subset must contain interval i) on interval i’s left.
- Say you are at element i and you need to find the dp[i]. To do this, go backward, traverse the dp array from i-1 to 0 and see if the current interval can be append to any subset with ending interval k (0 <= k <= i-1). The max covered length of all possibilities will be assigned to dp[i]. (Use the prevBound to cache the previous bound. It doesn’t have to keep going if it is over the bound from previous round)
- return Max(ap). (do this by constantly update the max)
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class IntervalDP {
public static void main(String[] args) {
// TODO Auto-generated method stub
IntervalDP dp = new IntervalDP();
List<Interval> intervals = initIntervals();
int c = dp.getMaxCoverage(intervals);
System.out.println(c);
}
private static List<Interval> initIntervals() {
List<Interval> list = new ArrayList<Interval>();
int[] start = { 0, 1, 3, 7, 10 };
int[] end = { 2, 2, 9, 8, 12 };
for (int i = 0; i < start.length; i++) {
list.add(new Interval(start[i], end[i]));
}
return list;
}
public int getMaxCoverage(List<Interval> intervals) {
if (intervals == null || intervals.isEmpty()) {
return 0;
}
int c = 0;
List<Interval> endIntervals = new ArrayList<Interval>(intervals);
Collections.sort(endIntervals, new EndComparator());
int[] dp = new int[intervals.size()];
//dp keeps going forward
for (int i = 0; i < dp.length; i++) {
Interval currentInterval = endIntervals.get(i);
int currentCover = currentInterval.end - currentInterval.start;
dp[i] = currentCover;
int prevBound = 0;
//At each interval, go backward, try update current max
for (int j = i; j >= 0; j--) {
Interval prevInterval = endIntervals.get(j);
if (currentInterval.start >= prevInterval.end) {
if (prevInterval.end <= prevBound) {
// Already compute in prev dp.
break;
}
prevBound = Math.max(prevBound, prevInterval.start);
dp[i] = Math.max(dp[i], dp[j] + currentCover);
}
c = Math.max(dp[i], c);
}
}
return c;
}
}
class Interval {
int start;
int end;
public Interval(int a, int b) {
start = a;
end = b;
}
}
class EndComparator implements Comparator<Interval> {
@Override
public int compare(Interval arg0, Interval arg1) {
return arg0.end - arg1.end;
}
}