当前位置: 首页 > article >正文

插入区间[中等]

优质博文:IT-BLOG-CN

一、题目

给你一个无重叠的 ,按照区间起始端点排序的区间列表。在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。

示例 1:
输入:intervals = [[1,3],[6,9]], newInterval = [2,5]
输出:[[1,5],[6,9]]

示例 2:
输入:intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
输出:[[1,2],[3,10],[12,16]]
解释:这是因为新的区间[4,8][3,5],[6,7],[8,10]重叠。

示例 3:
输入:intervals = [], newInterval = [5,7]
输出:[[5,7]]

示例 4:
输入:intervals = [[1,5]], newInterval = [2,3]
输出:[[1,5]]

示例 5:
输入:intervals = [[1,5]], newInterval = [2,7]
输出:[[1,7]]

0 <= intervals.length <= 104
intervals[i].length == 2
0 <= intervals[i][0] <= intervals[i][1] <= 105
intervals根据intervals[i][0]按升序排列
newInterval.length == 2
0 <= newInterval[0] <= newInterval[1] <= 105

二、代码

对于区间S1=[l1,r1]S2=[l2,r2]],如果它们之间没有重叠(没有交集),说明要么S1S2的左侧,此时有r1<l2​;要么S1S2的右侧,此时有l1>r2​。

如果r1<l2l1>r2二者均不满足,说明S1S2必定有交集,它们的交集即为[max⁡(l1,l2),min⁡(r1,r2)]并集即为[min⁡(l1,l2),max⁡(r1,r2)]

模拟: 在给定的区间集合X互不重叠的前提下,当我们需要插入一个新的区间S=[left,right]时,我们只需要:
【1】找出所有与区间S重叠的区间集合X′
【2】将X′中的所有区间连带上区间S合并成一个大区间;
【3】最终的答案即为不与X′重叠的区间以及合并后的大区间;

这样做的正确性在于,给定的区间集合中任意两个区间都是没有交集的,因此所有需要合并的区间,就是所有与区间S重叠的区间。并且,在给定的区间集合已经按照左端点排序的前提下,所有与区间S重叠的区间在数组intervals中下标范围是连续的,因此我们可以对所有的区间进行一次遍历,就可以找到这个连续的下标范围。

当我们遍历到区间[li,ri]时:
【1】如果ri<left,说明[li,ri]S不重叠并且在其左侧,我们可以直接将[li,ri]加入答案;
【2】如果li>right,说明[li,ri]S不重叠并且在其右侧,我们可以直接将[li,ri]加入答案;
【3】如果上面两种情况均不满足,说明[li,ri]S重叠,我们无需将[li,ri]加入答案。此时,我们需要将S[li,ri]合并,即将S更新为其与[li,ri]的并集。

那么我们应当在什么时候将区间S加入答案呢?由于我们需要保证答案也是按照左端点排序的,因此当我们遇到第一个 满足li>right的区间时,说明以后遍历到的区间不会与S重叠,并且它们左端点一定会大于S的左端点。此时我们就可以将S加入答案。特别地,如果不存在这样的区间,我们需要在遍历结束后,将S加入答案。

class Solution {
    public int[][] insert(int[][] intervals, int[] newInterval) {
        int left = newInterval[0];
        int right = newInterval[1];
        boolean placed = false;
        List<int[]> ansList = new ArrayList<int[]>();
        for (int[] interval : intervals) {
            if (interval[0] > right) {
                // 在插入区间的右侧且无交集
                if (!placed) {
                    ansList.add(new int[]{left, right});
                    placed = true;                    
                }
                ansList.add(interval);
            } else if (interval[1] < left) {
                // 在插入区间的左侧且无交集
                ansList.add(interval);
            } else {
                // 与插入区间有交集,计算它们的并集
                left = Math.min(left, interval[0]);
                right = Math.max(right, interval[1]);
            }
        }
        if (!placed) {
            ansList.add(new int[]{left, right});
        }
        int[][] ans = new int[ansList.size()][2];
        for (int i = 0; i < ansList.size(); ++i) {
            ans[i] = ansList.get(i);
        }
        return ans;
    }
}

时间复杂度: O(n),其中n是数组intervals的长度,即给定的区间个数。
空间复杂度: O(1)。除了存储返回答案的空间以外,我们只需要额外的常数空间即可。


http://www.kler.cn/news/149864.html

相关文章:

  • 自定义中间件
  • vue本地存储
  • 27. 移除元素
  • Vue组件库推荐:Element UI深度解析
  • 【新手解答1】深入探索 C 语言:变量名、形参 + 主调函数、被调函数 + 类和对象 + 源文件(.c 文件)、头文件(.h 文件)+ 库
  • 记一篇Centos7安装innodb_ruby
  • HarmonyOS-Service服务开发(一)
  • 删除排序链表的重复元素I和II,多种解法和思考
  • 拼多多发布Q3财报,Temu成第二增长引擎
  • harmonyos应用开发者高级认证考试部分答案(2)
  • 蓝桥杯day02——第三大的数
  • 线性表之链式表
  • 网工内推 | 中高级网工,IE认证优先,带薪年假,五险一金
  • Windows如何启动MySQL
  • [Linux] linux防火墙
  • 科普 | 隧道代理IP,简化操作提升安全性
  • vue3+vite打包自动生成dist.zip文件
  • JVM
  • 智能合约安全漏洞与解决方案
  • Unity 关于Input类的使用
  • 惠威M200MKII音箱拆机
  • 手摸手Element-ui组件化开发
  • 【C/C++】常见模拟题题解
  • React 和 Vue 在技术层面有哪些区别?
  • JSON.stringify,JSON.parse
  • Linux下文件操作函数
  • 【Linux】 sudo命令使用
  • 每日一题(LeetCode)----哈希表--两数之和
  • ArkUI开发进阶—@Builder函数@BuilderParam装饰器的妙用与场景应用【鸿蒙专栏-05】
  • el-table合并行