1. 程式人生 > 其它 >貪心演算法:合併區間

貪心演算法:合併區間

56. 合併區間

以陣列intervals表示若干個區間的集合,其中單個區間為intervals[i] = [starti, endi]。請你合併所有重疊的區間,並返回一個不重疊的區間陣列,該陣列需恰好覆蓋輸入中的所有區間。

輸入:intervals = [[1,3],[2,6],[8,10],[15,18]]
輸出:[[1,6],[8,10],[15,18]]
解釋:區間 [1,3] 和 [2,6] 重疊, 將它們合併為 [1,6].

輸入:intervals = [[1,4],[4,5]]
輸出:[[1,5]]
解釋:區間 [1,4] 和 [4,5] 可被視為重疊區間。

思路

按照左邊界從小到大排序之後,如果 intervals[i][0] < intervals[i - 1][1] 即intervals[i]左邊界 < intervals[i - 1]右邊界,則一定有重複,因為intervals[i]的左邊界一定是大於等於intervals[i - 1]的左邊界。

用合併區間後左邊界和右邊界,作為一個新的區間,加入到result數組裡。如果沒有合併就把原區間加入到result陣列。

程式碼

class Solution {
    public int[][] merge(int[][] intervals) {
        Arrays.sort(intervals, new Comparator<int[]>() {
            //左邊界升序排列
            public int compare(int[] point1, int[] point2) {
                if (point1[0] > point2[0]) {
                    return 1;
                } else if (point1[0] < point2[0]) {
                    return -1;
                } else {
                    return 0;
                }
            }
        });


        boolean flag = false; // 標記最後一個區間有沒有合併
        int length = intervals.length;
        List<int[]> ans = new ArrayList<int[]>();
        for (int i = 1; i < length; i++) {
            int start = intervals[i - 1][0];    // 初始為i-1區間的左邊界
            int end = intervals[i - 1][1];      // 初始i-1區間的右邊界
            while (i < length && intervals[i][0] <= end) { // 合併區間
                end = Math.max(end, intervals[i][1]);    // 不斷更新右區間
                if (i == length - 1) flag = true;   // 最後一個區間也合併了
                i++;                                // 繼續合併下一個區間
            }
            // start和end是表示intervals[i - 1]的左邊界右邊界,所以最優intervals[i]區間是否合併了要標記一下
            ans.add(new int[]{start, end});
        }
        // 如果最後一個區間沒有合併,將其加入result
        if (flag == false) {
            ans.add(new int[]{intervals[length - 1][0], intervals[length - 1][1]});
        }
        return ans.toArray(new int[ans.size()][]);
    }
}