力扣hot100-合并区间

目录

前言

思路分析

代码示例

总结


前言

        本文主要介绍的是力扣hot100里的56. 合并区间,核心思路就是排序→遍历→合并

思路分析

        要彻底理解 “合并区间” 问题的解法,将从问题本质、步骤拆解、边界处理三个维度展开分析:

        一、问题本质:区间的 “重叠判定” 与 “范围扩张”区间重叠的核心逻辑是:若区间 A 的右端点 ≥ 区间 B 的左端点,则 A 和 B 可以合并,合并后的区间左端点为 A 的左端点,右端点为max(A的右端点, B的右端点)。

        二、步骤拆解:“排序→遍历→合并” 的递进逻辑

        1. 排序:让重叠区间 “相邻”如果区间不排序,可能出现 “非相邻但实际重叠” 的情况(比如 [1,5] 和 [2,3] 被 [6,7] 隔开)。因此必须先按左端点排序,保证后续遍历中,所有可能重叠的区间都是相邻的。排序的依据是区间的左端点(intervals[i][0]),C++ 的sort会自动按二维数组的第一个元素升序排列。

        2. 遍历:用 “指针 + 循环” 管理合并过程我们用指针i遍历所有区间,同时维护 “当前合并区间” 的左右端点left和right:

                初始阶段:left和right初始化为当前区间(intervals[i])的左右端点。

                合并阶段:检查下一个区间(intervals[i+1])的左端点是否 ≤ right:若满足 → 合并,更新right为max(right, intervals[i+1][1]),并将i后移(处理下一个可能重叠的区间)。若不满足 → 停止合并,将当前[left, right]加入结果集,然后i后移处理新的区间组。

        3. 合并:从 “单个区间” 到 “区间组” 的抽象“合并区间” 的过程可以理解为将连续的 “重叠区间链” 压缩为一个区间。例如:输入 [[1,2],[2,3],[3,4]] → 三个区间可合并为 [1,4],因为每个后续区间的左端点都 ≤ 前一个的右端点。

        三、边界处理:覆盖所有特殊场景好的算法必须处理边界情况,本解法天然覆盖以下场景:空输入:若intervals为空,直接返回空数组(代码中while(i < n)不会执行,ans自然为空)。单个区间:若只有一个区间(n=1),循环执行一次,直接将其加入结果集。完全包含:如 [1,5] 和 [2,3],合并后为 [1,5](通过max(right, intervals[i+1][1])保证)。连续区间:如 [1,4] 和 [4,5],合并后为 [1,5](因为4 ≥ 4满足重叠条件)。

        四、时间与空间复杂度分析

        时间复杂度:O(nlogn),其中n是区间数量。排序的时间复杂度是O(nlogn),遍历区间的时间是O(n),整体由排序主导。

        空间复杂度:O(n),最坏情况下(所有区间都不重叠)需要存储n个区间;排序也需要O(n)的临时空间。

代码示例

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        // 获取区间数组的长度
        int n = intervals.size();
        // 遍历指针,用于遍历所有区间
        int i = 0;
        // 处理空数组的特殊情况,直接返回空数组
        if (n == 0) return {};
        vector<vector<int>> ans;
        // 临时存储当前正在合并的区间
        vector<int> upinterval;
        // 按区间左端点从小到大排序,为后续合并做准备
        sort(intervals.begin(), intervals.end());
        
        while (i < n) {
            // 每次处理新的区间组前,清空临时存储的区间
            upinterval.clear();
            // 记录当前合并区间的左端点
            int left = intervals[i][0];
            // 记录当前合并区间的右端点
            int right = intervals[i][1];
            
            // 合并所有重叠的区间:只要存在下一个区间且下一个区间的左端点 <= 当前合并区间的右端点
            while (i + 1 < n && right >= intervals[i + 1][0]) {
                // 更新合并区间的右端点(取当前右端点和下一个区间右端点的最大值)
                right = max(right, intervals[i + 1][1]);
                // 指针后移,处理下一个区间
                i++;
            }
            
            // 将合并后的区间存入临时容器
            upinterval.push_back(left);
            upinterval.push_back(right);
            // 将临时容器中的区间加入结果集
            ans.push_back(upinterval);
            // 指针后移,处理下一组区间
            i++;
        }
        
        return ans;
    }
};

总结

        以上就是本文的主要内容,想借这题和大家分享一下先排再写的做题思路,熟悉了这种思路,很多题都可以迎刃而解,希望这篇文章能够帮到一些码友。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值