hot100-合并区间(day14)

一、问题定义与核心需求

题目描述

传送门:合并区间

给定一个由若干区间组成的数组 intervals(单个区间为 [start_i, end_i]),合并所有重叠的区间,返回一个不重叠的区间数组,要求恰好覆盖输入的所有区间。

核心示例

输入 输出 核心逻辑
[[1,3],[2,6],[8,10],[15,18]] [[1,6],[8,10],[15,18]] [1,3] 与 [2,6] 重叠,合并为 [1,6]
[[1,4],[4,5]] [[1,5]] 端点相等视为重叠
[[4,7],[1,4]] [[1,7]] 区间乱序时需先排序再合并

关键认知

重叠的判定规则:若区间 A 的右端点 ≥ 区间 B 的左端点,则 A 和 B 重叠(包括端点相等的情况)。

二、思路拆解:从暴力到最优

1. 暴力思路(O (n²),不推荐)

核心逻辑
  • 遍历每个区间,与结果集中的所有区间逐一比较,若重叠则合并,否则加入结果集;
  • 合并后需重新检查结果集(因为新合并的区间可能和其他区间重叠)。
问题
  • 时间复杂度高(O (n²)),n 为区间数量;
  • 逻辑冗余,重复检查导致效率低下;
  • 乱序区间需多次回溯,极易出错。
结论

暴力思路仅适合理解 "重叠判定"。

2. 最优思路:排序 + 贪心(O (n log n),推荐)

核心原理
  • 排序 :先按区间的左端点升序排序,保证后续遍历的区间左端点不会小于前面的区间;
  • 贪心 :遍历排序后的区间,仅需与结果集中最后一个区间比较(因为排序后,若当前区间与最后一个不重叠,则与前面所有区间都不重叠)。

三、最优解代码实现与逐行解析

cpp 复制代码
class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        // 边界条件:空输入直接返回空结果
        if (intervals.empty()) return {};
        
        // 步骤1:按区间左端点升序排序(核心!)
        // sort默认按vector第一个元素升序,第二个元素升序
        sort(intervals.begin(), intervals.end());
        
        // 步骤2:初始化结果集,加入第一个区间
        vector<vector<int>> res;
        res.push_back(intervals[0]);
        
        // 步骤3:遍历剩余区间,贪心合并
        for (int i = 1; i < intervals.size(); ++i) {
            // 取结果集最后一个区间(引用,直接修改)
            vector<int>& last = res.back();
            // 当前区间的左端点
            int curr_start = intervals[i][0];
            // 当前区间的右端点
            int curr_end = intervals[i][1];
            
            // 判定:最后一个区间的右端点 ≥ 当前区间左端点 → 重叠
            if (last[1] >= curr_start) {
                // 合并:更新最后一个区间的右端点为两者最大值
                last[1] = max(last[1], curr_end);
            } else {
                // 不重叠:直接加入结果集
                res.push_back(intervals[i]);
            }
        }
        
        return res;
    }
};

关键代码解析

  1. 空输入处理 :if (intervals.empty()) return {};原代码未处理空输入,会导致 res.push_back(intervals[0]) 越界,这是面试高频坑点!
  2. 排序逻辑 :sort(intervals.begin(), intervals.end())C++ 的 sort 对二维 vector 默认按第一个元素升序排序,若第一个元素相等则按第二个元素升序,完全符合需求。
  3. 引用操作 :vector<int>& last = res.back();使用引用直接修改结果集最后一个区间,避免拷贝,提升效率。
  4. 合并规则 :last[1] = max(last[1], curr_end)必须取最大值(比如 [1,5] 和 [2,3] 重叠,合并后仍为 [1,5])。

四、复杂度分析

操作 时间复杂度 空间复杂度
排序 O(n log n) O (log n)(排序的栈空间)
遍历 O(n) O (1)(仅临时变量)
总复杂度 O(n log n) O (n)(结果集空间,若不计则为 O (log n))

五、常见坑点与避坑指南

  1. 忽略空输入 :未处理 intervals.empty() 会导致数组越界;
  2. 排序遗漏:忘记排序直接遍历,会导致乱序区间无法正确合并(如示例 3);
  3. 合并时取最小值 :错误写成 last[1] = min(...),完全违背合并逻辑;
  4. 端点相等判定错误 :认为 [1,4] 和 [4,5] 不重叠,不符合题目要求。

六、拓展:区间问题的延伸应用

  1. 区间插入:给定一个无重叠区间数组,插入一个新区间并合并(核心逻辑:先插入再合并);
  2. 无重叠区间:找出需要移除的最少区间数,使剩余区间无重叠(贪心:按右端点排序,选最早结束的区间);
  3. 会议室预订:判断能否安排所有会议(本质是检查是否有重叠区间)。

七、总结

  1. 合并区间的核心是排序 + 贪心:排序保证遍历顺序,贪心仅需比较最后一个区间,时间复杂度最优;
  2. 边界条件(空输入、端点相等);
  3. 区间类问题的本质是排序 + 重叠判定,掌握这两个核心可解决 80% 的区间题。
相关推荐
mmmmath_32 小时前
LeetCode.199.二叉树的右视图
数据结构·leetcode
专注仿真2 小时前
引擎扩展性与集成设计深度剖析:从 14 个扩展点到 DIS→HLA 演进之路
开发语言·算法·仿真引擎·推演引擎
码爸2 小时前
支持向量机介绍与示例
算法·机器学习·支持向量机
怕浪猫3 小时前
2028编程圈很火的10个Skills
算法·面试·github
别动我齐刘海4 小时前
Linux 系统调试学习1
linux·运维·服务器·c++·学习·机器学习·机器人
Nil2087 小时前
leetcode 198打家劫舍
算法·leetcode·职场和发展
Shaoshing7 小时前
前缀和与差分
java·数据结构·算法·前缀和·差分
mmmmath_37 小时前
LeetCode.429.N叉树的层序遍历
数据结构·leetcode
loulanyue_8 小时前
构建房产认知决策智能:Harness底座与AI自进化的技术实践——读贝壳首席算法科学家尹俊希2026云栖专场演讲
人工智能·算法
碧海银沙音频科技研究院8 小时前
基于炬芯ATS录音卡BLE控制协议
人工智能·嵌入式硬件·算法·语音识别