[LeetCode#57]Insert Interval

本文详细介绍了如何在已排序的区间集合中插入并合并新的区间,通过找到首个碰撞区间,逐步更新新区间边界,直至遍历完整个集合。最终实现对区间的有效管理与优化。

The problem:

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

My first solution:

The logic behind this solution is complex and errors prone! It's because I have not totally understand the rational behind this problem.

public class Solution {
    public List<Interval> insert(List<Interval> intervals, Interval newInterval) {
        ArrayList<Interval> ret = new ArrayList<Interval> ();
        if (intervals == null) {
            //return ret.add(newInterval);
            ret.add(newInterval);
            return ret;
        }
        if (newInterval == null)
            return intervals;
        
        Interval pre = new Interval(newInterval.start, newInterval.end);
        boolean flag = false; //indicate if the new Interval has already been added
        for (int i = 0; i < intervals.size(); i++) {
            Interval cur = intervals.get(i);
            if ((cur.start>=pre.start&&cur.start<=pre.end)||(cur.end>=pre.start&&cur.end<=pre.end)||(cur.end>=pre.end&&pre.start>=cur.start)) {//overlapping happens
                pre.start = pre.start < cur.start ? pre.start : cur.start;
                pre.end = pre.end > cur.end ? pre.end : cur.end;
            } else {
                if (pre.end < cur.start && flag != true) {  //the pre interval's range is over!
                    ret.add(pre);
                    flag = true; //casue I put off the add of the answer at next independent interval
                }
                ret.add(cur);
            }
        }
        
        if (flag != true)//in the case of the last interval!
            ret.add(pre);
        return ret;
    }
}

A more elegant way!!!

A advanced analysis

The idea behind this solution is simple and great, you must master related skills.
The key idea:
         [   ...   ]
[ ][ ][    ][  ][    ][]
we should able to figure out the first and last overlapping intervals with newInterval.
1. how to find out the first?  
At the first collision interval, as shown above, the start boundary must less than the end boundary of the first.
We use the contradiction as loop condition: before the first collision, the intervals end boundary must ahead of the newInterval's start boundary. Use this property, we could reach the first collision window. note the loop condition.
int i = 0;
while(i<intervals.size() && (newInterval.start>intervals.get(i).end)) { //only when not collision, we move on.
    ret.add(intervals.get(i));
    i++;
}

2. As the same, once we dectect the first collision, begin from the interval, all collision interval's start boundary must less
than the newInterval's start boundary. 
while (i<intervals.size() && (newInterval.end>=intervals.get(i).start)) {
    newInterval.end = newInterval.end > intervals.get(i).end ? newInterval.end : intervals.get(i).end;
    i++;
}

Since we detect the first overlapping interval, until we reach the last interval, we keep on merge newInterval through following ways: 
...
if (i < intervals.size()) {//must not exceed the end!!!
    newInterval.start = newInterval.start < intervals.get(i).start ? newInterval.start : intervals.get(i).start;
}

while (i<intervals.size() && (newInterval.end>=intervals.get(i).start)) {
    newInterval.end = newInterval.end > intervals.get(i).end ? newInterval.end : intervals.get(i).end;
    i++;
}
The while loop is because that, the checking codition is "newInterval.end>=intervals.get(i).start)", when means when the interval meets the condition of collision, we merge it into the collision interval. 

The solution:

public class Solution {
    public List<Interval> insert(List<Interval> intervals, Interval newInterval) {
        ArrayList<Interval> ret = new ArrayList<Interval> ();
        if (intervals == null || intervals.size() == 0) {
            ret.add(newInterval);
            return ret;
        }
        if (newInterval == null)
            return intervals;
            
        int i = 0;
        while(i<intervals.size() && (newInterval.start>intervals.get(i).end)) {
            ret.add(intervals.get(i));
            i++;
        }
        if (i < intervals.size()) {//must not exceed the end!!!
            newInterval.start = newInterval.start < intervals.get(i).start ? newInterval.start : intervals.get(i).start;
        }
        while (i<intervals.size() && (newInterval.end>=intervals.get(i).start)) {
            newInterval.end = newInterval.end > intervals.get(i).end ? newInterval.end : intervals.get(i).end;
            i++;
        }
        ret.add(newInterval);
        while (i<intervals.size()) {
            ret.add(intervals.get(i));
            i++;
        }
        return ret;
    }
}

 

转载于:https://www.cnblogs.com/airwindow/p/4225375.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值