题目
- 描述: 给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。
- 示例:
输入:[ [1,2], [2,3], [3,4], [1,3] ]
输出:1
解释: 移除[1,3]
后,剩下的区间没有重叠 - 思路:
- 从区间集合 intvs 中选择一个区间 x,这个 x 是在当前所有区间中结束最早的(end 最小),从而使用贪心策略。
- 把所有与 x 区间相交的区间从区间集合 intvs 中删除。
- 重复步骤 1 和 2,直到 intvs 为空为止。之前选出的那些 x 就是最大不相交子集。
说明: 排序后可方便选取结束值最小的区间, 开始值大于最小end的区间为满足条件的区间, 将其并入后更新最小end.
-
代码:
public static int eraseOverlapIntervals(int[][] intervals) { if (intervals.length == 0) return 0; // 按end升序排序 Arrays.sort(intervals, new Comparator<int[]>() { @Override public int compare(int[] o1, int[] o2) { return o1[1] - o2[1]; } }); // 至少有一个区间不相交 int count = 1; // 排序后,第一个区间就是x int x_end = intervals[0][1]; for (int[] interval : intervals) { int start = interval[0]; if (start >= x_end) {// 找到了合适的区间 count++; x_end = interval[1]; } } return count; }
-
笔记:
- 贪心算法是动态规划的特例, 相比动态规划,使用贪心算法需要满足贪心选择性质(每一步都做出一个局部最优的选择,最终的结果就是全局最优), 贪心算法效率比动态规划要高.
通俗例子:
比如你面前放着 100 张rmb,你只能拿十张,怎么才能拿最多的面额?显然每次选择剩下rmb中面值最大的一张,最后你的选择一定是最优的。可用贪心算法求解.
如打牌,对手出对儿三,按照贪心策略,你应该出尽可能小的牌刚好压制住对方,但现实情况我们甚至可能会出王炸。这种情况就不能用贪心算法,而得使用动态规划解决. - Arrays.sort可使用匿名内部类的方式,自定义排序比较逻辑, 示例中是按升序排序
Arrays.sort(intervals, new Comparator<int[]>() { @Override public int compare(int[] o1, int[] o2) { return o1[1] - o2[1]; } });
参考: 无重叠区间题解