1. 程式人生 > >[LeetCode] Insert Interval 插入區間

[LeetCode] Insert Interval 插入區間

Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).

You may assume that the intervals were initially sorted according to their start times.

Example 1:
Given intervals [1,3],[6,9], insert and merge [2,5] in as [1,5],[6,9].

Example 2:
Given [1,2],[3,5],[6,7],[8,10],[12,16]

, insert and merge [4,9] in as [1,2],[3,10],[12,16].

This is because the new interval [4,9] overlaps with [3,5],[6,7],[8,10].

這道題讓我們在一系列非重疊的區間中插入一個新的區間,可能還需要和原有的區間合併,那麼我們需要對給區間集一個一個的遍歷比較,那麼會有兩種情況,重疊或是不重疊,不重疊的情況最好,直接將新區間插入到對應的位置即可,重疊的情況比較複雜,有時候會有多個重疊,我們需要更新新區間的範圍以便包含所有重疊,之後將新區間加入結果res,最後將後面的區間再加入結果res即可。具體思路是,我們用一個變數cur來遍歷區間,如果當前cur區間的結束位置小於要插入的區間的起始位置的話,說明沒有重疊,則將cur區間加入結果res中,然後cur自增1。直到有cur越界或有重疊while迴圈退出,然後再用一個while迴圈處理所有重疊的區間,每次用取兩個區間起始位置的較小值,和結束位置的較大值來更新要插入的區間,然後cur自增1。直到cur越界或者沒有重疊時while迴圈退出。之後將更新好的新區間加入結果res,然後將cur之後的區間再加入結果res中即可,參見程式碼如下:

解法一:

class Solution {
public:
    vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
        vector<Interval> res;
        int n = intervals.size(), cur = 0;
        while (cur < n && intervals[cur].end < newInterval.start) {
            res.push_back(intervals[cur
++]); } while (cur < n && intervals[cur].start <= newInterval.end) { newInterval.start = min(newInterval.start, intervals[cur].start); newInterval.end = max(newInterval.end, intervals[cur].end); ++cur; } res.push_back(newInterval); while (cur < n) { res.push_back(intervals[cur++]); } return res; } };

下面這種方法的思路跟上面的解法很像,只不過沒有用while迴圈,而是使用的是for迴圈,但是思路上沒有太大的區別,變數cur還是用來記錄新區間該插入的位置,稍有不同的地方在於在for迴圈中已經將新區間後面不重疊的區間也加進去了,for迴圈結束後就只需要插入新區間即可,參見程式碼如下:

解法二:

class Solution {
public:
    vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
        vector<Interval> res;
        int n = intervals.size(), cur = 0;
        for (int i = 0; i < n; ++i) {
            if (intervals[i].end < newInterval.start) {
                res.push_back(intervals[i]);
                ++cur;
            } else if (intervals[i].start > newInterval.end) {
                res.push_back(intervals[i]);
            } else {
                newInterval.start = min(newInterval.start, intervals[i].start);
                newInterval.end = max(newInterval.end, intervals[i].end);
            }
        }
        res.insert(res.begin() + cur, newInterval);
        return res;
    }
};

下面這種解法就是把上面解法的for迴圈改為了while迴圈,其他的都沒有變,程式碼如下:

解法三:

class Solution {
public:
    vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
        vector<Interval> res;
        int n = intervals.size(), cur = 0, i = 0;
        while (i < n) {
            if (intervals[i].end < newInterval.start) {
                res.push_back(intervals[i]);
                ++cur;
            } else if (intervals[i].start > newInterval.end) {
                res.push_back(intervals[i]);
            } else {
                newInterval.start = min(newInterval.start, intervals[i].start);
                newInterval.end = max(newInterval.end, intervals[i].end);
            }
            ++i;
        }
        res.insert(res.begin() + cur, newInterval);
        return res;
    }
};

如果學過Design Pattern的,對Iterator Pattern比較熟悉的也可應用Iterator來求解,本質還是一樣的,只是寫法略有不同,程式碼如下:

解法四:

class Solution {
public:
    vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
        vector<Interval> res;
        vector<Interval>::iterator it = intervals.begin();
        int cur = 0;
        while (it != intervals.end()) {
            if (it->end < newInterval.start) {
                res.push_back(*it);
                ++cur;
            } else if (it->start > newInterval.end) {
                res.push_back(*it);
            } else {
                newInterval.start = min(newInterval.start, it->start);
                newInterval.end = max(newInterval.end, it->end);
            }
            ++it;
        }
        res.insert(res.begin() + cur, newInterval);
        return res;
    }
};

類似題目:

參考資料: