Find longest covered length of non overlapping interval subsets

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

  1. 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.
  2. 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)
  3. 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;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值