【算法训练-排序算法 三】【排序应用】合并区间

简介: 【算法训练-排序算法 三】【排序应用】合并区间

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【合并区间】,使用【数组】这个基本的数据结构来实现,这个高频题的站点是:CodeTop,筛选条件为:目标公司+最近一年+出现频率排序,由高到低的去牛客TOP101去找,只有两个地方都出现过才做这道题(CodeTop本身汇聚了LeetCode的来源),确保刷的题都是高频要面试考的题。

明确目标题后,附上题目链接,后期可以依据解题思路反复快速练习,题目按照题干的基本数据结构分类,且每个分类的第一篇必定是对基础数据结构的介绍

合并区间【MID】

一道一直想要解决的高频题,用到了排序

题干

解题思路

如果我们按照区间的左端点排序,那么在排完序的列表中,可以合并的区间一定是连续的。如下图所示,标记为蓝色、黄色和绿色的区间分别可以合并成一个大区间,它们在排完序的列表中是连续的

我们用数组 merged 存储最终的答案。

  • 首先,我们将列表中的区间按照左端点升序排序。然后我们将第一个区间加入 merged 数组中,并按顺序依次考虑之后的每个区间:
  • 如果当前区间的左端点在数组 merged 中最后一个区间的右端点之后,那么它们不会重合,我们可以直接将这个区间加入数组 merged 的末尾;
  • 否则,它们重合,我们需要用当前区间的右端点更新数组 merged 中最后一个区间的右端点,将其置为二者的较大值。

总体思路是左端点从小到大排列,每次比较只要比较新区间的左端点是否在已合并区间右端点之后就可以了,在之后则独立,在之前则重叠(而且由于左端点升序,在之前也是在之前已合并区间的中间,极端情况是和已排序区间左端点重叠)

代码实现

给出代码实现基本档案

基本数据结构数组

辅助数据结构

算法快速排序(分治算法)、二分查找

技巧双指针

import java.util.*;
/*
 * public class Interval {
 *   int start;
 *   int end;
 *   public Interval(int start, int end) {
 *     this.start = start;
 *     this.end = end;
 *   }
 * }
 */
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param intervals Interval类ArrayList
     * @return Interval类ArrayList
     */
    public ArrayList<Interval> merge (ArrayList<Interval> intervals) {
        // 1 先对集合进行排序
        intervals.sort(Comparator.comparingInt(interval -> interval.start));
        // 2 遍历顺序数组进行合并
        ArrayList<Interval> result = new ArrayList<Interval>();
        for (Interval interval : intervals) {
            // 2-1 获取当前区间左右端点和已合并区间右端点
            int leftPoint = interval.start;
            int rightPoint = interval.end;
            // 2-2 如果结果区间为空或者当前区间左端点大于已合并区间右端点,则当前区间作为独立子区间加入集合
            if (result.size() == 0 || leftPoint > result.get(result.size() - 1).end) {
                result.add(interval);
            } else {
            // 2-3 否则认为当前区间与已合并区间有重叠,只需更新合并区间右端点
                result.get(result.size() - 1).end =  Math.max(result.get(result.size() - 1).end, rightPoint);
            }
        }
        return result;
    }
}

leetcode数组入参的处理方法:

import java.util.*;
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param n int整型 the n
     * @return int整型
     */
    public int[][] merge(int[][] intervals) {
        // 1 先对数组进行排序
        Arrays.sort(intervals, Comparator.comparingInt(interval->interval[0]));
        // 2 遍历已排序数组,进行区间合并
        int[][] result = new int[intervals.length][2];
        int idx = -1;
        for (int[] interval : intervals) {
            // 2-1 获取当前区间左右边界以及合并区间右边界
            int leftPoint = interval[0];
            int rightPoint = interval[1];
            // 2-2 如果已合并区间为空,或当前区间左端点大于已合并区间右端点,则不重叠
            if (idx == -1 || result[idx][1] < leftPoint) {
                idx++;
                result[idx] = interval;
            } else {
                // 2-3 反之则重叠,已两个区间较大值为新的右边界
                result[idx][1] = Math.max(result[idx][1], rightPoint);
            }
        }
        return Arrays.copyOf(result, idx + 1);
    }
}

复杂度分析

合并区间是一个常见的算法问题,通常用于合并具有重叠部分的区间,以简化问题或提供更清晰的表示。以下是关于合并区间问题的时间复杂度和空间复杂度的讨论:

时间复杂度:

时间复杂度是衡量算法性能的关键指标,它表示算法在输入规模增加时所需的运行时间。对于合并区间问题,一种常见的解决方法是首先将区间按照起始值进行排序,然后遍历这些区间并合并它们。

  1. 排序:对区间按照起始值进行排序通常需要 O(n*log(n)) 的时间复杂度,其中 n 是区间的数量。
  2. 遍历和合并:一旦区间排序完成,遍历区间并合并重叠的部分通常需要线性时间,即 O(n)

因此,综合来看,合并区间的时间复杂度通常是 O(n*log(n)),其中 n 是区间的数量。这是由排序操作的时间复杂度主导的。

空间复杂度:

空间复杂度表示算法在执行过程中所需的额外内存空间。对于合并区间问题,空间复杂度通常取决于存储合并后的区间的数据结构。

  1. 如果您在原始区间上就地修改,而不创建额外的数据结构,则空间复杂度是 O(1),因为不需要额外的内存空间。
  2. 如果您创建一个新的数据结构来存储合并后的区间,空间复杂度将取决于这个数据结构的大小。通常情况下,合并后的区间数目会少于或等于初始区间数目,因此空间复杂度也是 O(n)

总结:合并区间问题的时间复杂度通常是 O(n*log(n)),空间复杂度可以是 O(1) 或 O(n),具体取决于是否创建了新的数据结构来存储合并后的区间。

拓展知识:Arrays的用法

Arrays的一些用法拓展描述下

Arrays.copyOf(result, x)描述了什么

Arrays.copyOf(result, x) 是一个Java方法,它的含义是创建一个新数组,这个新数组的长度为 x,并且将原始数组 result 中的元素复制到新数组中。如果 x 小于原始数组的长度,那么新数组将截断,只包含原始数组中前 x 个元素。如果 x 大于原始数组的长度,新数组将在末尾用默认值填充,这个默认值取决于元素的数据类型,例如,数值类型默认是0,引用类型默认是null

这个方法允许你在不改变原始数组的情况下创建一个具有不同长度的新数组,非常方便,特别是在需要调整数组大小时。例如:

int[] result = {1, 2, 3, 4, 5};
int x = 8; // 新数组的长度
int[] newArray = Arrays.copyOf(result, x);
// 新数组现在将会是 {1, 2, 3, 4, 5, 0, 0, 0},长度为 8

在这个示例中,Arrays.copyOf 创建了一个长度为8的新数组,并将原始数组 result 中的元素复制到新数组中,多出的部分用0填充。

Arrays.sort(intervals, Comparator.comparingInt(interval->interval[0])) 描述下这个语句做了什么

这个语句使用了 Java 中的 Arrays.sort 方法来对一个二维数组 intervals 进行排序。排序是基于二维数组中每个子数组的第一个元素(interval[0])的值来进行的,也就是按照子数组的起始值进行排序。

具体来说,这行代码的功能是:

  1. intervals 是一个二维整数数组,通常用于表示区间(例如,区间的起始和结束值)。
  2. Arrays.sort 是 Java 中用于对数组进行排序的方法。
  3. Comparator.comparingInt(interval -> interval[0]) 是一个比较器,它告诉排序方法要按照每个子数组的第一个元素(interval[0])的值进行升序排序。

所以,这个语句将根据 intervals 中每个子数组的第一个元素(起始值)来对二维数组进行排序,从小到大排列。排序后,intervals 数组中的子数组将按照它们的起始值从小到大的顺序排列。

这对于处理区间的问题非常有用,因为它可以将区间按照起始值进行排序,使得你可以更轻松地执行各种区间操作,比如合并重叠区间或查找包含某个点的区间等操作。

目录
打赏
0
0
0
0
33
分享
相关文章
MapReduce在实现PageRank算法中的应用
总结来说,在实现PageRank算法时使用MapReduce能够有效地进行大规模并行计算,并且具有良好的容错性和可扩展性。
103 76
从第十批算法备案通过名单中分析算法的属地占比、行业及应用情况
2025年3月12日,国家网信办公布第十批深度合成算法通过名单,共395款。主要分布在广东、北京、上海、浙江等地,占比超80%,涵盖智能对话、图像生成、文本生成等多行业。典型应用包括医疗、教育、金融等领域,如觅健医疗内容生成算法、匠邦AI智能生成合成算法等。服务角色以面向用户为主,技术趋势为多模态融合与垂直领域专业化。
JavaScript 中通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能,JS中排序算法的使用详解(附实际应用代码)
Array.sort() 是一个功能强大的方法,通过自定义的比较函数,可以处理各种复杂的排序逻辑。无论是简单的数字排序,还是多字段、嵌套对象、分组排序等高级应用,Array.sort() 都能胜任。同时,通过性能优化技巧(如映射排序)和结合其他数组方法(如 reduce),Array.sort() 可以用来实现高效的数据处理逻辑。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
从第九批深度合成备案通过公示名单分析算法备案属地、行业及应用领域占比
2024年12月20日,中央网信办公布第九批深度合成算法名单。分析显示,教育、智能对话、医疗健康和图像生成为核心应用领域。文本生成占比最高(57.56%),涵盖智能客服、法律咨询等;图像/视频生成次之(27.32%),应用于广告设计、影视制作等。北京、广东、浙江等地技术集中度高,多模态融合成未来重点。垂直行业如医疗、教育、金融加速引入AI,提升效率与用户体验。
基于生物地理算法的MLP多层感知机优化matlab仿真
本程序基于生物地理算法(BBO)优化MLP多层感知机,通过MATLAB2022A实现随机数据点的趋势预测,并输出优化收敛曲线。BBO模拟物种在地理空间上的迁移、竞争与适应过程,以优化MLP的权重和偏置参数,提升预测性能。完整程序无水印,适用于机器学习和数据预测任务。
基于LSB最低有效位的音频水印嵌入提取算法FPGA实现,包含testbench和MATLAB对比
本项目展示了一种基于FPGA的音频水印算法,采用LSB(最低有效位)技术实现版权保护与数据追踪功能。使用Vivado2019.2和Matlab2022a开发,完整代码含中文注释及操作视频。算法通过修改音频采样点的最低有效位嵌入水印,人耳难以察觉变化。然而,面对滤波或压缩等攻击时,水印提取可能受影响。该项目运行效果无水印干扰,适合实时应用场景,核心逻辑简单高效,时间复杂度低。
基于GA遗传算法的拱桥静载试验车辆最优布载matlab仿真
本程序基于遗传算法(GA)实现拱桥静载试验车辆最优布载的MATLAB仿真,旨在自动化确定车辆位置以满足加载效率要求(0.95≤ηq≤1.05),目标是使ηq尽量接近1,同时减少车辆数量和布载耗时。程序在MATLAB 2022A版本下运行,展示了工况1至工况3的测试结果。通过优化模型,综合考虑车辆重量、位置、类型及车道占用等因素,确保桥梁关键部位承受最大荷载,从而有效评估桥梁性能。核心代码实现了迭代优化过程,并输出最优布载方案及相关参数。
基于MobileNet深度学习网络的活体人脸识别检测算法matlab仿真
本内容主要介绍一种基于MobileNet深度学习网络的活体人脸识别检测技术及MQAM调制类型识别方法。完整程序运行效果无水印,需使用Matlab2022a版本。核心代码包含详细中文注释与操作视频。理论概述中提到,传统人脸识别易受非活体攻击影响,而MobileNet通过轻量化的深度可分离卷积结构,在保证准确性的同时提升检测效率。活体人脸与非活体在纹理和光照上存在显著差异,MobileNet可有效提取人脸高级特征,为无线通信领域提供先进的调制类型识别方案。
基于模糊神经网络的金融序列预测算法matlab仿真
本程序为基于模糊神经网络的金融序列预测算法MATLAB仿真,适用于非线性、不确定性金融数据预测。通过MAD、RSI、KD等指标实现序列预测与收益分析,运行环境为MATLAB2022A,完整程序无水印。算法结合模糊逻辑与神经网络技术,包含输入层、模糊化层、规则层等结构,可有效处理金融市场中的复杂关系,助力投资者制定交易策略。