LeetCode 57. 插入区间

57. 插入区间

 

 

【有序集合+区间合并】将所有区间放入一个有序集合中,按照左端点排序,对于新区间new[start, end],寻找第一个左端点<=end的区间(floor方法),判断这个区间的右端点是否>=start,如果是就合并(合并方法其实就是取new和这个区间左端点的较小值,右端点的较大值),并删除掉原来的区间,然后继续寻找下一个符合条件能合并的区间,直到所有在覆盖范围内的区间都被合并起来。退出while循环后将最新的[start, end]加入集合即可。

class Solution {

    // 有序集合 11:52 12:05

    public int[][] insert(int[][] intervals, int[] newInterval) {
        TreeSet<int[]> set = new TreeSet<int[]>((a, b) -> {return a[0] - b[0];});
        for(var it: intervals) set.add(it);
        int start = newInterval[0], end = newInterval[1];
        int[] key = set.floor(new int[] {end, end});
        while(key != null){
            if(key[1] < start) break;
            start = Math.min(start, key[0]);
            end = Math.max(end, key[1]);
            set.remove(key);
            key = set.floor(new int[] {end, end});
        }
        set.add(new int[] {start, end});
        int[][] ans = new int[set.size()][];
        int i = 0;
        for(var k: set){
            ans[i++] = k;
        }
        return ans;
    }
}

【二分+区间合并】 突然发现区间已经有序,所以不用再开TreeSet了(其实用TreeSet)主要为了用他的floor方法,可以直接用二分来查,然后找到下标后继续往前找下标就行了。

class Solution {

    // 二分 10:00 10:19

    public int[][] insert(int[][] intervals, int[] newInterval) {
        int start = newInterval[0], end = newInterval[1];
        int n = intervals.length, left = 0, right = n - 1;
        while(left <= right){
            int mid = (left + right) >>> 1;
            if(intervals[mid][0] > end) right = mid - 1;
            else left = mid + 1;
        }
        int idx = right;
        if(idx < 0){
            int[][] ans = new int[n + 1][];
            ans[0] = newInterval;
            int i = 1;
            for(var it: intervals) ans[i++] = it; 
            return ans;
        }
        else{
            int t = 0;
            while(true && idx >= 0){
                left = intervals[idx][0];
                right = intervals[idx][1];
                if(right < start) break;
                intervals[idx][0] = -1;
                t++;
                start = Math.min(start, left);
                end = Math.max(end, right);
                idx--;
            }
            n = n - t + 1;
            idx++;
            int[][] ans = new int[n][];
            int i, j;
            for(i = 0, j = 0; i < n; i++){
                if(i == idx) ans[i] = new int[] {start, end};
                else{
                    while(intervals[j][0] == -1) j++;
                    ans[i] = intervals[j++];
                }
            }
            return ans;
        }
    }
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值