ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

LeetCode合并区间算法解析与应用场景

LeetCode合并区间算法解析与应用场景

1. 合并区间问题概述

LeetCode第56题"合并区间"是算法面试中的经典问题,也是Hot100高频题目之一。题目要求给定一个区间的集合,合并所有重叠的区间。这个问题看似简单,但考察了程序员对排序算法、数组操作和边界条件处理等基础能力的掌握程度。

在实际工程中,合并区间的场景非常常见。比如处理日程安排时合并重叠时间段、优化数据库查询的时间范围、合并网络设备的IP地址段等。掌握这个算法不仅能帮助通过技术面试,更能提升解决实际问题的能力。

2. 问题分析与解题思路

2.1 问题描述

给定一个区间的集合,其中每个区间表示为[start, end]。需要合并所有重叠的区间,并返回一个不重叠的区间数组。

示例: 输入:intervals = [[1,3],[2,6],[8,10],[15,18]] 输出:[[1,6],[8,10],[15,18]] 解释:区间[1,3]和[2,6]重叠,合并为[1,6]

2.2 关键观察点

  1. 区间重叠的判断标准:两个区间[a,b]和[c,d],如果a≤d且c≤b,则它们重叠
  2. 合并后的新区间取两个区间的最小开始值和最大结束值
  3. 输入区间可能无序,直接处理会导致复杂度高且难以正确合并

2.3 解题思路

最直观的解法是:

  1. 首先将所有区间按照起始点排序
  2. 初始化结果列表,放入第一个区间
  3. 遍历后续区间,与结果列表最后一个区间比较:
    • 如果重叠,则合并
    • 否则直接加入结果列表

这种解法的时间复杂度主要取决于排序步骤,为O(nlogn),空间复杂度为O(n)(存储结果)。

3. 代码实现与详细解析

3.1 Python实现

def merge(intervals): if not intervals: return [] # 按区间起始点排序 intervals.sort(key=lambda x: x[0]) merged = [intervals[0]] for current in intervals[1:]: last = merged[-1] # 检查是否重叠 if current[0] <= last[1]: # 合并区间 last[1] = max(last[1], current[1]) else: merged.append(current) return merged

3.2 代码解析

  1. 首先处理空输入的特殊情况
  2. 使用Python内置的sort方法,按区间起始点排序
  3. 初始化merged列表,放入第一个区间
  4. 遍历后续区间:
    • 获取当前区间和merged中最后一个区间
    • 检查是否重叠(当前区间的起始点≤最后一个区间的结束点)
    • 如果重叠,则合并(取两个区间结束点的最大值)
    • 否则将当前区间加入merged列表

3.3 边界条件处理

  • 空输入:直接返回空列表
  • 单个区间:无需合并,直接返回
  • 完全包含的区间:如[1,4]和[2,3],合并为[1,4]
  • 刚好相接的区间:如[1,2]和[2,3],可以合并为[1,3]

4. 复杂度分析与优化

4.1 时间复杂度

  • 排序步骤:O(nlogn)
  • 合并步骤:O(n)
  • 总体时间复杂度:O(nlogn)

4.2 空间复杂度

  • 排序:Python的sort方法空间复杂度为O(n)
  • 存储结果:O(n)
  • 总体空间复杂度:O(n)

4.3 优化思路

  1. 如果输入已经有序,可以跳过排序步骤,时间复杂度降为O(n)
  2. 可以使用原地算法减少空间使用,但会牺牲代码可读性
  3. 对于特定场景(如区间范围有限),可以使用计数排序将时间复杂度降为O(n)

5. 常见错误与调试技巧

5.1 常见错误

  1. 忘记排序:导致无法正确识别所有重叠区间
  2. 合并逻辑错误:如只更新结束点而不比较最大值
  3. 边界条件处理不当:如空输入或单个区间的情况
  4. 修改遍历中的列表:在遍历时修改原列表会导致意外行为

5.2 调试技巧

  1. 打印中间结果:在排序后和每次合并后打印当前状态
  2. 使用可视化工具:绘制区间图帮助理解合并过程
  3. 单元测试:针对各种边界情况编写测试用例
  4. 逐步执行:使用调试器一步步跟踪程序执行

6. 实际应用场景

6.1 日程安排系统

合并用户的多段可用时间,找出连续的可用时间段。例如:

  • 输入:[[9,10],[10,12],[14,15],[13,14]]
  • 输出:[[9,12],[13,15]]

6.2 网络IP地址管理

合并连续的IP地址段,优化路由表。例如:

  • 输入:[[192.168.1.1,192.168.1.10],[192.168.1.5,192.168.1.15]]
  • 输出:[[192.168.1.1,192.168.1.15]]

6.3 数据库查询优化

合并多个查询条件的时间范围,减少查询次数。例如:

  • 输入:[[20230101,20230105],[20230103,20230110]]
  • 输出:[[20230101,20230110]]

7. 变种问题与扩展

7.1 插入新区间

给定一组不重叠的区间(已排序)和一个新区间,插入并合并必要的区间。这是LeetCode第57题,可以看作是合并区间问题的扩展。

7.2 区间交集

给定两组已排序的区间列表,返回它们的交集。这是LeetCode第986题,需要同时遍历两个列表并比较区间。

7.3 会议室安排

给定一组会议时间区间,判断一个人是否能参加所有会议。这是LeetCode第252题,解法类似于检查是否有重叠区间。

8. 个人解题心得

在实际解决这个问题时,我最初尝试了不排序直接合并的方法,结果发现无法处理所有情况。经过几次失败后,我意识到排序是解决问题的关键步骤。这让我深刻理解到:对于区间问题,排序往往能大大简化问题复杂度。

另一个收获是关于边界条件的处理。最初我的代码在空输入时会出错,后来添加了相应的检查。这提醒我在解决算法问题时,一定要考虑各种边界情况,包括空输入、单个元素、完全包含等情况。

最后,我发现将这个问题可视化非常有帮助。画出区间在数轴上的表示,可以直观地理解合并的过程和条件。这种可视化思维在解决其他区间问题时也同样适用。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进