LeetCode第57题插入区间

继续打卡算法题,今天学习的是LeetCode第57题插入区间,这道题目是道中等题。算法题的一些解题思路和技巧真的非常巧妙,每天看一看算法题和解题思路,我相信对我们的编码思维和编码能力有一些提升。

分析一波题目

上一题56题合并区间 已经学习了怎么判断重叠区间,怎么合并区间,本题就不难了。最简单的做法,我们可以把要插入的区间和原区间集合先添加到一个新的区间集合,然后排序,最后做一次合并,后面的流程和56题一样。

java 复制代码
        int[][] newIntervals = new int[intervals.length+1][1];
        System.arraycopy(intervals, 0, newIntervals, 0, intervals.length);
        newIntervals[newIntervals.length-1] = newInterval;
        Arrays.sort(newIntervals, (o1, o2) -> Integer.compare(o1[0], o2[0]));

通过上面的代码组成了新的区间集合,只要对newIntervals中重叠的区间进行合并,这个做法虽好理解,但是性能就降低了,因为题目已经说明原区间已经按左边界排序了,因此本题可以有更优的做法。

由于原区间集已经有序了,我们可以按如下步骤来执行插入操作。

1、将与要插入的区间无重叠的,加入到新的区间集

2、将与要插入的区间有重叠的,执行合并

3、将与要插入的区间无重叠的,加入到新的区间集

本题解题技巧

1、将原区间集分段,分为与新区间左边界偏离的一段,与新区间有重叠的,与新区间右边界偏离的一段

编码解决

重组区间集合,再排序解法

java 复制代码
class Solution {
    public int[][] insert(int[][] intervals, int[] newInterval) {

        //存储结果
        LinkedList<int[]> result = new LinkedList<>();
        //按左边界排序
        int[][] newIntervals = new int[intervals.length+1][1];
        //重组新区间集
        System.arraycopy(intervals, 0, newIntervals, 0, intervals.length);
        newIntervals[newIntervals.length-1] = newInterval;
        Arrays.sort(newIntervals, (o1, o2) -> Integer.compare(o1[0], o2[0]));
        System.out.println(newIntervals.length);
        //第一个先加入结果
        result.add(newIntervals[0]);
        //从第二个开始判断是否重叠
        for (int i = 1; i < newIntervals.length; i++) {
            //和前面的重叠了
             System.out.println(i);
            System.out.println(newIntervals[i]);
            if (newIntervals[i][0] <= result.getLast()[1]) {
                int start = result.getLast()[0];
                int end = Math.max(newIntervals[i][1], result.getLast()[1]);
                //合并之前,最后一个需要删除
                result.removeLast();
                //合并成新区间,并加入结果
                result.add(new int[]{start, end});
            }
            else {
                //没有重叠,加入结果
                result.add(newIntervals[i]);
            }   
        }
        return result.toArray(new int[result.size()][]);
    }
}

不重组区间集且不重新排序解法

java 复制代码
class Solution {
    public int[][] insert(int[][] intervals, int[] newInterval) {
        //存储结果
        int[][] result = new int[intervals.length + 1][2];
        int idx = 0;
        
        // 1、首先将新区间左边且相离的区间加入结果集
        int i = 0;
        while (i < intervals.length && intervals[i][1] < newInterval[0]) {
            result[idx++] = intervals[i++];
        }
        // 2、接着判断当前区间是否与新区间重叠,重叠的话就进行合并
        while (i < intervals.length && intervals[i][0] <= newInterval[1]) {
            newInterval[0] = Math.min(intervals[i][0], newInterval[0]);
            newInterval[1] = Math.max(intervals[i][1], newInterval[1]);
            i++;
        }
        //合并的结果存入
        result[idx++] = newInterval;

        // 3、最后将新区间右边且相离的区间加入结果集
        while (i < intervals.length) {
            result[idx++] = intervals[i++];
        }

        return Arrays.copyOf(result, idx);
    }
}

总结

1、通过借助56题合并区间思路,可以解决本题,合并区间和判断区间重叠的方法同样适用

2、借助原区间集本身有序的特性,通过拆分3步,根据新区间和原区间集的关系,要么有交集,要么在区间集左边,执行插入操作,并且时间复杂度控制在O(n)。

相关推荐
龚思凯1 分钟前
Node.js 模块导入语法变革全解析
后端·node.js
天行健的回响4 分钟前
枚举在实际开发中的使用小Tips
后端
wuhunyu10 分钟前
基于 langchain4j 的简易 RAG
后端
techzhi10 分钟前
SeaweedFS S3 Spring Boot Starter
java·spring boot·后端
写bug写bug1 小时前
手把手教你使用JConsole
java·后端·程序员
苏三说技术1 小时前
给你1亿的Redis key,如何高效统计?
后端
JohnYan2 小时前
工作笔记- 记一次MySQL数据移植表空间错误排除
数据库·后端·mysql
程序员清风2 小时前
阿里二面:Kafka 消费者消费消息慢(10 多分钟),会对 Kafka 有什么影响?
java·后端·面试
CodeSheep2 小时前
宇树科技,改名了!
前端·后端·程序员
hstar95273 小时前
三十五、面向对象底层逻辑-Spring MVC中AbstractXlsxStreamingView的设计
java·后端·spring·设计模式·架构·mvc