1. 程式人生 > 其它 >LeetCode435. 無重疊區間

LeetCode435. 無重疊區間

技術標籤:LeetCode

  • 題目描述

給定一個區間的集合,找到需要移除區間的最小數量,使剩餘區間互不重疊。

注意

  1. 可以認為區間的終點總是大於它的起點。
  2. 區間 [1,2] 和 [2,3] 的邊界相互“接觸”,但沒有相互重疊。
  • 示例
輸入: [ [1,2], [2,3], [3,4], [1,3] ]
輸出: 1
解釋: 移除 [1,3] 後,剩下的區間沒有重疊
輸入: [ [1,2], [1,2], [1,2] ]
輸出: 2
解釋: 你需要移除兩個 [1,2] 來使剩下的區間沒有重疊
輸入: [ [1,2], [2,3] ]
輸出: 0
解釋: 你不需要移除任何區間,因為它們已經是無重疊的了
  • 分析 – 貪心演算法

貪心策略:優先保留結尾小且不相交的區

把區間按照結尾的大小進行增序排序,每次選擇結尾最小且和前一個選
擇的區間不重疊的區間

  • Code
class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        if (intervals.length < 2 ) {
            return 0;
        }

        Arrays.sort(intervals, new Comparator<int[]>() {
            @Override
public int compare(int[] o1, int[] o2) { return o1[1] - o2[1]; } }); int res = 0; int[] pre = intervals[0]; for (int i=1; i<intervals.length; i++) { int[] cur = intervals[i]; if (cur[0] < pre[1]) { res++
; } else { pre = cur; } } return res; } }

在這裡插入圖片描述

貪心策略:保留最小的區間
先按區間頭從小到大排序,再按照區間尾從小到大排序,保證區間的有序性
選擇不重疊的區間且最小

  • Code
class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        if (intervals.length < 2 ) {
            return 0;
        }

        Arrays.sort(intervals, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return (o1[0] == o2[0]) ? (o1[1] - o2[1]) : (o1[0] - o2[0]);
            }
        });

        int res = 0;
        int[] pre = intervals[0];
        for (int i=1; i<intervals.length; i++) {
            int[] cur = intervals[i];
            if (cur[0] == pre[0] && cur[1] >= pre[1]) { // pre 屬於 cur
                res++;
            } else if (cur[1] <= pre[1]) {      // cur 屬於 pre
                res++;
                pre = cur;
            } else if (cur[0] < pre[1]) {  // cur pre 相交
                res++;
            } else {
                pre = cur;
            }
        }
        return res;
    }
}

在這裡插入圖片描述

  • 複雜度分析

時間複雜度:排序的複雜度O(nlogn) 遍歷複雜度O(n)
空間複雜度:排序棧空間O(nlogn)