leetCode-hot100-数组专题之区间问题

数组专题之区间问题

    • 知识点:
    • 解决思路:
    • 例题
      • 56.合并区间
      • 57.插入区间
      • 253.会议室 Ⅱ
      • 485.无重叠区间

数组区间问题是算法中常见的一类问题,它们通常涉及对数组中的区间进行排序、合并、插入或删除操作。无论是合并区间、插入区间还是删除重复空间,首先都需要区分需要处理的区间的条件,主要是对区间左右边界的比较。以下是数组区间问题的知识点和解决思路的总结:

知识点:

  1. 区间表示:一个区间通常用两个数表示,第一个数是区间的起始点,第二个数是区间的结束点。
  2. 区间排序:如果区间的起始点不同,可以通过排序快速找到重叠的区间,在例题中使用了Arrays.sort(),自定义比较器:
//按照数组区间的第一个元素排序
Arrays.sort(intervals,(a,b) -> a[0] - b[0]);
//按照数组区间的第二个元素排序
Arrays.sort(intervals,(a,b) -> a[1]- b[1]);
  1. 合并区间:当两个区间的起始点不同,但一个区间的结束点大于或等于另一个区间的起始点时,这两个区间可以合并为一个区间。
  2. 插入区间:当需要将一个新的区间插入到已有的区间集合中时,需要考虑新区间与已有区间的关系,可能需要合并区间或调整区间顺序。
  3. 无重叠区间:当区间之间没有公共部分时,这些区间是无重叠的。

解决思路:

  1. 排序:对于区间问题,通常首先需要对区间进行排序,以便于后续操作。排序可以按照起始点进行,也可以按照结束点进行。
  2. 合并区间:(56)
    • 遍历排序后的区间,检查当前区间是否可以与前一个区间合并。
    • 如果可以合并,更新合并后的区间的起始点和结束点。
    • 继续遍历,直到处理完所有区间。
  3. 插入区间:(57)
    • 遍历排序后的区间,找到插入位置。
    • 如果新区间与当前区间重叠,需要合并区间。
    • 更新插入后的区间顺序。
    • 继续遍历,直到处理完所有区间。
  4. 无重叠区间:(253、485)
    • 遍历排序后的区间,检查当前区间是否与前一个区间重叠。
    • 不重叠的条件是后一个区间的左边界大于等于前一个区间的右边界
      在解决区间问题时,通常需要考虑区间的特殊性质,比如区间的大小、起始点和结束点等。此外,还需要注意边界条件,比如空区间、只有一个区间的情况等。通过以上知识点和解决思路,可以解决大多数基本的区间问题。

例题

56.合并区间

思路
本题使用扫描线法来解决,首先要对二维数组进行排序,根据其中数组元素的第一个数字进行升序排列(这里代码里用了一种正则表达式的排序方法,会在知识点总结进行介绍),在排序完成之后进行扫描,有三种情况,我们将最前面的数组区间设置为[start,end],向后扫描:

  1. 后面的区间的starti大于end,那么直接将前一个区间加入结果集中

  2. 后面的区间的starti小于end,这里又会分出两种情况:

    (1)后面的区间完全包含在前面的区间
    (2)后面的区间的endi大于前面区间的end
    以上两种情况我们都需要将end更新为最大的end值,所以可以归结为一类

如果还是不太理解的话可以点击视频讲解-合并区间。
时间复杂度
首先将区间按照起始时间排序,这需要O(nlogn)的时间复杂度,然后遍历排序后的区间,维护一个当前区间的起始时间和结束时间。如果遇到与当前区间重叠的新区间,就更新当前区间的结束时间。如果遇到与当前区间不重叠的新区间,就把当前区间加入到结果列表中,然后更新当前区间的起始时间和结束时间,这个遍历过程需要O(n)的时间复杂度。所以总的时间复杂度是O(nlogn) + O(n) = O(nlogn)
代码实现

class Solution {
    public int[][] merge(int[][] intervals) {
        //将ntervals按照数组元素的第一个数排序
        Arrays.sort(intervals,(a,b) -> a[0] - b[0]);
        List<int[]> ans = new ArrayList<>();
        int start = intervals[0][0];
        int end = intervals[0][1];
        for(int[] interval : intervals){
            if(interval[0] > end){
                ans.add(new int[]{start,end});
                start = interval[0];
                end = interval[1];
            }else{
                end = Math.max(end,interval[1]);
            }
        }
        ans.add(new int[]{start,end});
        return ans.toArray(new int[ans.size()][]);
    }
}

知识总结
1.List的常见使用

//向List中添加元素
List.add(e)
//根据索引获取元素
List.get(index)
//按照索引删除
List.remove(index)
//按照元素内容删除
List.remove(Object o)
//判断List中是否包含某个元素,返回true或false
List.contains(Object o)
//使用element替换该索引处的值
List.set(index,element)
//在该索引位置插入一个值
List.add(index,element)
//返回该值的第一个索引
List.indexOf(Object o)
//返回该值的最后一个索引
List.lastIndexOf(Object o)
//截取List的部分元素,
//注意这里时左闭右开,即fromIndex的值要包括,但是toIndex的值不包括,索引从0开始
List.subList(fromIndex, toIndex)
//返回该List中的元素数
List.size()
//对比两个List的所有元素是否相同
//两个相等对象的equals方法一定为true, 但两个hashcode相等的对象不一定是相等的对象
List1.equals(List2)
//判断List是否为空
List.isEmpty()
//返回Iterator集合对象
List.iterator()
//将List转换为字符串
List.toString()
//将List转换为数组
List.toArray()

2.二维数组的排序

Arrays.sort(intervals,(a,b) -> a[0] - b[0]);

intervals是一个二维数组,每个元素都是一个包含两个整数的数组,表示一个时间区间的开始和结束时间。(a, b) -> a[0] - b[0]是一个lambda表达式,用作排序的比较函数。它比较两个数组ab的第一个元素,如果a[0]小于b[0],则返回一个负数,表示a应该排在b前面。经过排序,intervals数组中的时间区间会按照开始时间的升序排列。
为什么不能直接使用Arrays.sort(intervals)呢?
由于 intervals 数组中的元素是 int[] 类型的数组。在这种情况下,直接使用 Arrays.sort(intervals) 是不正确的,因为 Java 默认使用数组元素的比较顺序进行排序,对于 int[] 类型来说,比较的是数组的引用,而不是数组中的元素。
对于一维数组,比如 int[] 类型,Arrays.sort() 方法可以直接使用,它会按照数组元素的自然顺序进行排序。
但是对于二维数组 int[][] 类型,情况就不太一样了。因为二维数组的元素是一维数组,所以 Arrays.sort() 默认是按照一维数组的引用进行排序的,而不是按照一维数组中的元素进行排序。
为了按照二维数组中的特定元素进行排序,需要提供一个自定义的比较器,例如 (a, b) -> a[0] - b[0] ,这样可以告诉 Arrays.sort() 方法按照二维数组中的第一个元素进行排序。

57.插入区间

思路:
根据题目要求可以将数组intervals分为三部分,第一部分为需要合并区间的左边部分,可以直接加入结果数组中,第二部分是需要和插入区间合并的区间,第三部分是合并后右侧剩下的区间,直接加入结果数组,区分每个部分的条件如下:
(1)左侧部分:所有数组元素的右边界应该小于插入元素的左边界(intervals[i][1] < newInterval[0]
(2)合并部分:所有数组元素的左边界应该小于插入元素的右边界(intervals[i][0] <= newInterval[1]
下面是一个简单画图说明;
在这里插入图片描述

时间复杂度:
这段代码的时间复杂度为O(n),其中nintervals数组的长度。
代码实现:

class Solution {
    public int[][] insert(int[][] intervals, int[] newInterval) {
        List<int[]> ans  = new ArrayList<>();
        int n = intervals.length;
        int i = 0;

        //加入合并区间左边部分的元素
        while(i < n && intervals[i][1] < newInterval[0]){
            ans.add(intervals[i++]);
        }

        //合并区间
        if(i < n){
            newInterval[0] = Math.min(intervals[i][0],newInterval[0]);
            while(i < n && intervals[i][0] <= newInterval[1]){
                newInterval[1] = Math.max(intervals[i++][1],newInterval[1]);
            }
        }
        ans.add(newInterval);

        //处理剩下的元素,即合并区间右边的元素
        while(i < n){
            ans.add(intervals[i++]);
        }

        return ans.toArray(new int[ans.size() - 1][]);
    }
}

253.会议室 Ⅱ

思路:
本题采用优先队列解决,使用一个升序排列的优先队列记录每个会议的结束时间,然后遍历数组,当后一个会议的开始时间大于前一个会议的结束时间时,说明两个会议并不冲突,此时前一个会议从优先队列中弹出,后一个会议加入优先队列;反之,前一个会议不弹出,并将后一个会议加入优先队列,可以看出此时队列的大小即为需要会议室的数量,最后处理完所有的会议后返回优先队列的大小即可。
时间复杂度:
这段代码的时间复杂度为O(nlogn),其中nintervals的长度。这是因为使用了优先队列来存储会议的结束时间,并进行了排序。优先队列的插入和删除操作的时间复杂度为O(logn),而插入和删除操作都被执行了n次,所以总的时间复杂度为O(nlogn)
代码实现:

class Solution {
    public int[][] merge(int[][] intervals) {
        if(intervals.length == 0) return 0;
        //使用优先队列来存储会议的结束时间
        //创建了一个容量为intervals.length的优先队列,按照整数元素的升序排列
        PriorityQueue<Integer> ans = new PriorityQueue<>(intervals.length, (a , b) -> a - b);
        ans.offer(intervals[0][1]);

        for(int i = 1; i < intervals.length ;i++){
            //会议不冲突时将其弹出,会议冲突时将冲突会议加入
            //最终优先队列的大小即为需要会议室的数量
            if(intervals[i][0] >= ans.peek()){
                ans.poll();
            }
            ans.offer(intervals[i][1]);
        }
        return ans.size();
    }
}

485.无重叠区间

思路:
本题需要得到移除区间的最小数量,得到一个不重叠的区间,这里首先将每个区间按照右边界来排序,因为右边界越小说明后面区间可以选择空间越大,这样移除的区间就是最少的。判断不是重叠区间的条件是区间的左边界大于等于上一个区间的右边界。
时间复杂度:
这段代码的时间复杂度为O(nlogn),其中nintervals数组的长度。代码中的Arrays.sort()函数的时间复杂度为O(nlogn),排序完成后,遍历intervals数组的时间复杂度是O(n),因此总的时间复杂度为O(nlogn)
代码实现:

class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        if(intervals.length < 2) return 0;
        //将数组按照右边升序排序
        Arrays.sort(intervals,(a,b) -> a[1]- b[1]);
        int cnt = 1;
        int end = intervals[0][1];
        //遍历数组,找到所有不重复的元素,条件是区间的左边界大于end
        //符合条件更新end值,并cnt+1
        for(int i = 1; i < intervals.length;i++){
            if(intervals[i][0] >= end){
                end = intervals[i][1];
                cnt++;
            }
        }
        //返回总数量减去不重叠区间的数量即为结果
        return intervals.length - cnt;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/634183.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

azure gpt 技术教程教学 | 在Azure OpenAI 上部署GPT-4o

Azure OpenAI GPT-4o是OpenAI推出的最新旗舰级人工智能模型。GPT-4o模型设计为能够实时对音频、视觉和文本进行推理&#xff0c;这是迈向更自然人机交互的重要一步。该模型的一大特点是能够处理多种类型的数据输入和输出&#xff0c;包括文本、音频和图像&#xff0c;实现了跨模…

适用于Windows 电脑的最佳视频恢复软件和方法

毫无疑问&#xff0c;丢失您的基本数据总是有压力的&#xff0c;尤其是当这些是您为捕捉最美好回忆而收集的重要视频文件时。要恢复丢失或损坏的视频文件&#xff0c;您可以借助视频恢复工具。但是&#xff0c;在选择最佳视频恢复工具时&#xff0c;您必须考虑多个扫描选项&…

Windows10安装python3.8.2

1、下载与安装 下载地址&#xff1a;https://www.python.org/downloads/release/python-382/ 滑动到页面底部 下载好的安装包安装到合适的位置&#xff08;默认安装到C盘&#xff09; 安装的时候&#xff0c;见到Add Python 3.8 to PATH 记得勾选. 2、检测安装是否成功 cm…

Facebook隐私保护:数据安全的前沿挑战

在数字化时代&#xff0c;随着社交媒体的普及和应用&#xff0c;个人数据的隐私保护问题日益受到关注。作为全球最大的社交平台之一&#xff0c;Facebook承载了数十亿用户的社交活动和信息交流&#xff0c;但与此同时&#xff0c;也面临着来自内外部的数据安全挑战。本文将深入…

Flask Response 对象

文章目录 创建 Response 对象设置响应内容设置响应状态码设置响应头完整的示例拓展设置响应的 cookie重定向响应发送文件作为响应 总结 Flask 是一个 Python Web 框架&#xff0c;用于快速开发 Web 应用程序。在 Flask 中&#xff0c;我们使用 Response 对象来构建 HTTP 响应。…

汽车IVI中控开发入门及进阶(十九):监控视频图像分割处理

图像分割是一种计算机视觉技术,可将数字图像分成离散的像素组(图像分段),为对象检测和相关任务提供信息。通过将图像的复杂视觉数据解析为特定形状的片段,图像分割可以实现更快、更先进的图像处理。 图像分割技术的范围很广,从简单直观的启发式分析到最前沿的深度学习实…

【论文笔记】advPattern

【论文题目】 advPattern: Physical-World Attacks on Deep Person Re-Identification via Adversarially Transformable Patterns Abstract 本文首次尝试对深度reID实施鲁棒的物理世界攻击。提出了一种新颖的攻击算法&#xff0c;称为advPattern&#xff0c;用于在衣服上生成…

CR80清洁卡都能用在什么地方?

CR80清洁卡&#xff08;也被称为ISO 7810 ID-1清洁卡&#xff09;的规格确实使其在各种需要读取磁条或接触式智能卡的设备中都有广泛的用途。这些设备包括但不限于&#xff1a; ATM自动终端机&#xff1a;当ATM机的磁条读卡器出现故障或读卡不灵敏时&#xff0c;可以使用CR80清…

H800基础能力测试

H800基础能力测试 参考链接A100、A800、H100、H800差异H100详细规格H100 TensorCore FP16 理论算力计算公式锁频安装依赖pytorch FP16算力测试cublas FP16算力测试运行cuda-samples 本文记录了H800基础测试步骤及测试结果 参考链接 NVIDIA H100 Tensor Core GPU Architecture…

CVPR2022医疗图像-GBCNet网络:胆囊癌(GBC)超声(USG)图像检测模型

Surpassing the Human Accuracy:Detecting Gallbladder Cancer from USG Images with Curriculum Learning&#xff1a;超越人类的准确性:基于课程学习的USG图像检测胆囊癌 目录 一、背景与意义 二、介绍 三、网络框架 3.1 区域选择网络 3.2 MS-SoP分类器 3.3 多尺度块 …

linux创建离线yum源给局域网机器使用

适用场景&#xff1a;在封闭的内网环境中&#xff0c;无法使用互联网进行安装各种rpm包的时候&#xff0c;离线yum源可以解决大部分问题&#xff0c;配置号后可直接使用yum进行安装包 1.准备好镜像源ISO&#xff1a; 例如以下示例&#xff0c;具体可参考自己的系统进行下载&a…

vscode插件-07Java

文章目录 Extension Pack for JavaSpring Initializr Java SupportCodeSwingJdk下载JDK安装jdkWindows安装jdkLinux安装jdk&#xff08;以Ubuntu为例&#xff09; jdk环境变量在VScode中配置Windows系统中配置Linux系统中配置&#xff08;以Ubuntu为例&#xff09; Extension P…

文心一言 VS 讯飞星火 VS chatgpt (265)-- 算法导论20.1 4题

四、假设不使用一棵叠加的度为 u \sqrt{u} u ​ 的树&#xff0c;而是使用一棵叠加的度为 u 1 k u^{\frac{1}{k}} uk1​的树&#xff0c;这里 k 是大于 1 的常数&#xff0c;则这样的一棵树的高度是多少&#xff1f;又每个操作将需要多长时间&#xff1f;如果要写代码&#xf…

DiskCatalogMaker for Mac:专业的文件搜索与整理助手

DiskCatalogMaker for Mac&#xff0c;这款专业的文件搜索与整理助手&#xff0c;为Mac用户带来了全新的文件管理体验。它不仅能快速扫描和读取各种存储设备中的文件&#xff0c;还能创建详细的磁盘目录数据库&#xff0c;使用户能够轻松查找和管理所需文件。 软件的搜索功能强…

HP1010|图腾柱无桥PFC电流采样模式小结

伴随着氮化镓和碳化硅等第三代半导体功率器件在应用端的兴起&#xff0c;图腾柱PFC也随之从学术研究走到了现实的产品里。然而&#xff0c;在受益于拓扑电路简洁&#xff0c;高功率密度和效率的同时&#xff0c; 还是有很多技术难点是需要克服的。本文将讨论图腾柱PFC电流采样&…

xrdp多用户多控制界面远程控制

1、无桌面安装桌面&#xff08;原本有ubuntu桌面的可以直接跳过这一步&#xff09; Gnome 与 xfce 相比&#xff0c;xfce 由于其轻巧&#xff0c;它可以安装在低端台式机上。Xfce 优雅的外观&#xff0c;增强了用户体验&#xff0c;它对用户非常友好&#xff0c;性能优于其他桌…

Excel 下划线转驼峰

Excel 下划线转驼峰 LOWER(LEFT(SUBSTITUTE(PROER(A1),"_",""),1))&RIGHT(SUBSTITUTE(PROPER(A1),"_",""),LEN(SUBSTITUTE(PROPER(A1),"_",""))-1)

【kubernetes】kubeadmin

确定需求 #master的cpu核心数要求大于2 master&#xff08;2C/4G&#xff09; 192.168.10.19 docker、kubeadm、kubelet、kubectl、flannel node01&#xff08;2C/2G&#xff09; 192.168.10.20 docker、kubeadm、kubelet、kubectl、flannel node02&#xff08;2C/2…

单链表oj

练习 1. 删除val节点 oj链接 这道题最先想出来的方法肯定是在遍历链表的同时删除等于val的节点&#xff0c;我们用第二中思路:不等于val的节点尾插&#xff0c;让后返回新节点。代码如下&#xff1a; struct ListNode* removeElements(struct ListNode* head, int val) {str…

5. JVM面试题汇总

Java全栈面试题汇总目录-CSDN博客 1. 说一下JVM的主要组成部分及其作用? JVM包含两个子系统和两个组件&#xff0c;两个子系统为Class loader(类装载)、Execution engine(执行引擎)&#xff1b;两个组件为Runtime data area(运行时数据区)、Native Interface(本地接口)。 Cl…