[Leetcode] Merge Intervals and Insert Interval 合併間隔與插入間隔

Merge Intervals

最新更新請見 https://yanjia.me/zh/2019/02/...

Given a collection of intervals, merge all overlapping intervals.

For example, Given [1,3],[2,6],[8,10],[15,18], return [1,6],[8,10],[15,18].數組

排序法

複雜度

時間 O(NlogN) 空間 O(N)app

思路

首先根據Interval的起點,咱們將其排序,這樣能合併的Interval就必定是相鄰的了:code

[1,3] [5,6] [2,3]
---> [1,3] [2,3] [5,6]

而後咱們就順序遍歷這個列表,並記錄一個當前待合併的Interval,若是遍歷到的Interval和當前待合併的Interval有重複部分,咱們就將兩個合併,若是沒有重複部分,就將待合併的Interval加入結果中,並用新的Interval更新這個待合併的Interval。由於數組已經排過序,前面的Interval的起點確定小於後面Interval的起點,因此在判斷是否有重疊部分時,只要考慮待合併的Interval的終點和遍歷到的Interval的起點的關係就好了。排序

注意

  • 判斷重疊的邊界時包含等於的狀況
  • 循環後還要把最後一個待合併的Interval也加入結果中
  • 更新待合併Interval的邊界時,要同時更新起點和終點

代碼

public class Solution {
    public List<Interval> merge(List<Interval> intervals) {
        List<Interval> res = new LinkedList<Interval>();
        if(intervals.size() == 0){
            return res;
        }
        // 按照起點排序
        Collections.sort(intervals, new Comparator<Interval>(){
            public int compare(Interval i1, Interval i2){
                return i1.start - i2.start;
            }
        });
        // 拿出第一個待合併的Interval
        Interval curr = intervals.get(0);
        for(Interval itv : intervals){
            // 若是有重疊部分,更新待合併的Interval的起點和終點
            if(curr.end >= itv.start){
                curr.start = Math.min(curr.start, itv.start);
                curr.end = Math.max(curr.end, itv.end);
            } else {
            // 不然將待合併的Interval加入結果中,並選取新的待合併Interval
                res.add(curr);
                curr = itv;
            }
        }
        // 將最後一個待合併的加進結果
        res.add(curr);
        return res;
    }
}

Insert Interval

最優解請見:https://yanjia.me/zh/2019/02/...

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.leetcode

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

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].it

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

排序法

複雜度

時間 O(NlogN) 空間 O(N)class

思路

和Merge Interval的思路接近,這題中咱們只有一個待合併的Interval,就是輸入給出的。咱們只要把全部和該Interval有重疊的合併到一塊兒就好了。爲了方便操做,對於那些沒有重疊部分的Interval,咱們能夠把在待合併Interval以前的Interval加入一個列表中,把以後的Interval加入另外一個列表中。最後把前半部分的列表,合併後的大Interval和後半部分的列表連起來,就是結果了。List

注意

  • 由於待合併的Interval出現的位置不肯定,判斷重疊與否時既要判斷起點,也要判斷終點
  • 原列表爲空時,直接加入待合併的Interval後返回

代碼

public class Solution {
    public List<Interval> insert(List<Interval> intervals, Interval newInterval) {
        List<Interval> before = new LinkedList<Interval>();
        List<Interval> after = new LinkedList<Interval>();
        List<Interval> res = new LinkedList<Interval>();
        if(intervals.size() == 0){
            res.add(newInterval);
            return res;
        }
        // 排序
        Collections.sort(intervals, new Comparator<Interval>(){
            public int compare(Interval i1, Interval i2){
                return i1.start - i2.start;
            }
        });
        for(Interval itx : intervals){
            // 將待合併Interval以前的存入一個列表中
            if(newInterval.start > itx.end){
                before.add(itx);
            }
            // 將有重疊的Interval都合併起來
            if((newInterval.end >= itx.start && newInterval.end <= itx.end) || (newInterval.start <= itx.end && newInterval.start >= itx.start)){
                newInterval.start = Math.min(newInterval.start, itx.start);
                newInterval.end = Math.max(newInterval.end, itx.end);
            }
            // 將待合併Interval以後的存入一個列表中
            if(newInterval.end < itx.start){
                after.add(itx);
            }
        }
        // 把三部分加起來
        res.addAll(before);
        res.add(newInterval);
        res.addAll(after);
        return res;
    }
}
相關文章
相關標籤/搜索