[LeetCode] 2406. Divide Intervals Into Minimum Number of Groups

CNoodle發表於2024-10-13

You are given a 2D integer array intervals where intervals[i] = [left, right] represents the inclusive interval [left, right].

You have to divide the intervals into one or more groups such that each interval is in exactly one group, and no two intervals that are in the same group intersect each other.

Return the minimum number of groups you need to make.

Two intervals intersect if there is at least one common number between them. For example, the intervals [1, 5] and [5, 8] intersect.

Example 1:
Input: intervals = [[5,10],[6,8],[1,5],[2,3],[1,10]]
Output: 3
Explanation: We can divide the intervals into the following groups:

  • Group 1: [1, 5], [6, 8].
  • Group 2: [2, 3], [5, 10].
  • Group 3: [1, 10].
    It can be proven that it is not possible to divide the intervals into fewer than 3 groups.

Example 2:
Input: intervals = [[1,3],[5,6],[8,10],[11,13]]
Output: 1
Explanation: None of the intervals overlap, so we can put all of them in one group.

Constraints:
1 <= intervals.length <= 105
intervals[i].length == 2
1 <= left <= right <= 106

將區間分為最少組數。

給你一個二維整數陣列 intervals ,其中 intervals[i] = [left, right] 表示 閉 區間 [left, right] 。

你需要將 intervals 劃分為一個或者多個區間 組 ,每個區間 只 屬於一個組,且同一個組中任意兩個區間 不相交 。

請你返回 最少 需要劃分成多少個組。

如果兩個區間覆蓋的範圍有重疊(即至少有一個公共數字),那麼我們稱這兩個區間是 相交 的。比方說區間 [1, 5] 和 [5, 8] 相交。

思路

此題思路同會議室 II。大致思路都是排序 + 比較,只是具體做法有些區別。以下請把 left 和 right 分別理解為一個會議的開始時間和結束時間。

思路一 - 排序 + 最小堆

初始化的時候對 input 按 開始時間 排序,然後準備一個最小堆,是用來放入所有會議的 結束時間。遍歷 input 陣列,因為 input 已經按 開始時間 排過序,所以對於某個 開始時間 而言,我們拿他去跟堆頂的最小的 結束時間 比較。如果 開始時間 跟 結束時間 有重疊,則說明這兩個會議時間是有交集的,一定要再開一個會議室(將當前結束時間放入堆中)。照著此題的題意就是這兩個區間一定不能分在同一組。最後最小堆的 size 就是會議室的數量 - 也就是分組的數量。

思路二 - 對 left 和 right 分別排序

對會議的 開始時間 和 結束時間 分別排序。用雙指標的方式遍歷 開始時間 和 結束時間。如果某個 結束時間 比當前的 開始時間 小,則說明兩個會議沒有交集,可以分在同一組。如果某個 結束時間 比當前的 開始時間 大,則說明兩個會議有交集,就需要再加一組。最後返回組的數量。

複雜度

時間O(nlogn)
空間O(n)

程式碼

Java實現 - 排序 + 最小堆

class Solution {
    public int minGroups(int[][] intervals) {
        Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
        PriorityQueue<Integer> queue = new PriorityQueue<>((a, b) -> a - b);
        int n = intervals.length;
        for (int i = 0; i < n; i++) {
            int[] cur = intervals[i];
            if (!queue.isEmpty() && queue.peek() < cur[0]) {
                queue.poll();
            }
            queue.offer(cur[1]);
        }
        return queue.size();
    }
}

Java實現 - 對 left 和 right 分別排序

class Solution {
    public int minGroups(int[][] intervals) {
        // corner case
        if (intervals == null || intervals.length == 0) {
            return 0;
        }

        // normal case
        int n = intervals.length;
        int[] start = new int[n];
        int[] end = new int[n];
        for (int i = 0; i < n; i++) {
            start[i] = intervals[i][0];
            end[i] = intervals[i][1];
        }
        Arrays.sort(start);
        Arrays.sort(end);
        int res = 0;
        int pointer = 0;
        for (int i = 0; i < n; i++) {
            if (start[i] <= end[pointer]) {
                res++;
            } else {
                pointer++;
            }
        }
        return res;
    }
}

相關題目

252. Meeting Rooms
253. Meeting Rooms II
2406. Divide Intervals Into Minimum Number of Groups

相關文章