news 2026/8/18 4:03:55

LeetCode 986题解:双指针法处理区间交集问题

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LeetCode 986题解:双指针法处理区间交集问题

1. 问题背景与核心挑战

LeetCode 986题"Interval List Intersections"是一个经典的区间处理问题,主要考察对有序区间的操作能力。题目给定两个已排序的区间列表,要求返回这两个列表中所有区间的交集集合。这类问题在实际开发中非常常见,比如处理日程安排冲突、资源分配重叠等场景。

我刚接触这道题时,第一反应是"这不就是双指针的变种吗?",但实际编码时发现边界条件的处理远比想象中复杂。特别是当区间存在多种重叠情况时,稍不注意就会漏判或者重复计算。举个例子,区间A[1,5]和区间B[3,7]的交集是[3,5],而A[1,3]和B[4,6]则没有交集。

2. 算法思路解析

2.1 双指针法的基本逻辑

解决这个问题的核心在于利用两个指针分别遍历两个区间列表。具体步骤如下:

  1. 初始化指针i和j,分别指向两个列表的起始位置
  2. 比较当前两个区间的起始和结束位置
  3. 计算可能存在的交集区间
  4. 移动结束位置较小的那个区间的指针
  5. 重复上述过程直到任一列表遍历完毕

关键点在于如何正确计算两个区间的交集。数学上,两个区间[a1, a2]和[b1, b2]的交集存在当且仅当a1 <= b2且b1 <= a2。如果存在交集,则交集区间为[max(a1,b1), min(a2,b2)]。

2.2 C语言实现细节

在C语言实现时,我们需要特别注意内存管理和数组操作。以下是核心代码片段:

int** intervalIntersection(int** firstList, int firstListSize, int* firstListColSize, int** secondList, int secondListSize, int* secondListColSize, int* returnSize, int** returnColumnSizes){ int **result = malloc(sizeof(int*) * (firstListSize + secondListSize)); *returnColumnSizes = malloc(sizeof(int) * (firstListSize + secondListSize)); *returnSize = 0; int i = 0, j = 0; while(i < firstListSize && j < secondListSize){ int a1 = firstList[i][0], a2 = firstList[i][1]; int b1 = secondList[j][0], b2 = secondList[j][1]; // 检查是否有交集 if(a2 >= b1 && b2 >= a1){ // 计算交集 int start = a1 > b1 ? a1 : b1; int end = a2 < b2 ? a2 : b2; // 存储结果 result[*returnSize] = malloc(sizeof(int)*2); result[*returnSize][0] = start; result[*returnSize][1] = end; (*returnColumnSizes)[*returnSize] = 2; (*returnSize)++; } // 移动指针 if(a2 < b2) i++; else j++; } return result; }

3. 边界条件与特殊处理

3.1 空输入处理

在实际编码中,我们必须考虑以下几种边界情况:

  • 其中一个列表为空
  • 两个列表都为空
  • 列表中存在空区间(如[3,3]表示单个点)

在C语言实现中,对空输入的处理尤为重要。例如,当firstListSize为0时,我们应该立即返回空数组,而不是继续执行后续逻辑。

3.2 内存管理要点

C语言需要手动管理内存,这里有几个关键注意事项:

  1. 预先分配足够大的结果数组(通常是两个列表大小之和)
  2. 为每个交集区间单独分配内存
  3. 记得为returnColumnSizes分配内存
  4. 调用者需要负责释放这些内存

一个常见的错误是忘记为returnColumnSizes分配内存,这会导致运行时错误。另一个陷阱是结果数组预分配过大造成内存浪费,或者过小导致越界。

4. 复杂度分析与优化

4.1 时间复杂度

该算法的时间复杂度是O(m+n),其中m和n分别是两个列表的长度。这是因为每个指针最多移动m+n次,每次操作都是常数时间。

4.2 空间复杂度

空间复杂度也是O(m+n),最坏情况下需要存储所有可能的交集区间。在实际应用中,如果交集很少,可以考虑动态调整内存分配策略,但这会增加代码复杂度。

5. 实际应用场景

这类区间交集问题在实际开发中有广泛应用:

  1. 会议系统:查找多个参与者的共同空闲时间
  2. 资源调度:确定设备可用的重叠时间段
  3. 基因组学:查找DNA序列的重叠区域
  4. 日志分析:找出多个服务同时出现异常的时段

理解这个算法不仅能帮助通过面试,更能为解决实际问题提供思路。例如,在处理用户行为日志时,我经常需要找出多个事件序列的共同发生时段,这时类似的区间处理技巧就派上用场了。

6. 常见错误与调试技巧

6.1 典型错误案例

在实现这个算法时,我遇到过几个典型的bug:

  1. 指针移动逻辑错误:错误地总是移动第一个指针
  2. 交集判断条件错误:遗漏了a2 >= b1的条件
  3. 内存分配不足:没有预分配足够的结果空间
  4. 忘记设置returnColumnSizes的值

6.2 调试建议

对于这类问题,我建议使用以下测试用例进行验证:

  1. 常规情况:

    • 输入:[[1,3],[5,9]] 和 [[2,5],[7,10]]
    • 预期输出:[[2,3],[5,5],[7,9]]
  2. 无交集情况:

    • 输入:[[1,3],[5,7]] 和 [[8,10]]
    • 预期输出:[]
  3. 完全包含情况:

    • 输入:[[1,7]] 和 [[3,5]]
    • 预期输出:[[3,5]]
  4. 单点区间:

    • 输入:[[1,1],[3,3]] 和 [[1,3]]
    • 预期输出:[[1,1],[3,3]]

在LeetCode上提交前,务必在本地用这些测试用例验证你的代码。特别是对于C语言实现,内存错误往往不会立即导致程序崩溃,但会在评测时产生不可预测的结果。

7. 扩展思考

7.1 变种问题

掌握了基础解法后,可以尝试解决一些变种问题:

  1. 处理未排序的区间列表(需要先排序)
  2. 合并多个区间列表的交集
  3. 计算交集的持续总时间
  4. 找出满足特定条件的最长交集

7.2 性能优化

对于特别大的区间列表,可以考虑以下优化:

  1. 提前终止:当剩余区间不可能再有交集时提前结束
  2. 并行处理:将列表分段后并行计算
  3. 区间压缩:预处理时合并相邻或重叠区间

不过在实际面试中,通常只需要实现基础解法即可,除非特别说明有性能要求。

8. 编码风格建议

在C语言实现这类算法题时,良好的编码风格很重要:

  1. 为指针操作添加注释
  2. 合理命名变量(如用i,j作指针,a1/a2表示区间端点)
  3. 保持函数单一职责(不要在一个函数里做太多事情)
  4. 添加必要的空行分隔逻辑块
  5. 为复杂条件添加解释性注释

例如,交集判断条件可以这样注释:

// Check if intervals overlap // a: [a1, a2], b: [b1, b2] // They overlap if a2 >= b1 && b2 >= a1 if(a2 >= b1 && b2 >= a1){ // ... }

这样的代码不仅更容易调试,也便于面试官理解你的思路。

9. 与其他语言的对比

虽然题目要求用C实现,但了解其他语言的解法也有助于加深理解:

Python可以利用列表推导简化代码:

def intervalIntersection(A, B): i = j = 0 res = [] while i < len(A) and j < len(B): a_start, a_end = A[i] b_start, b_end = B[j] # Calculate overlap start = max(a_start, b_start) end = min(a_end, b_end) if start <= end: res.append([start, end]) # Move pointer if a_end < b_end: i += 1 else: j += 1 return res

Java则需要处理更多的样板代码,但思路相同。相比之下,C语言版本虽然更冗长,但执行效率通常更高,也更能体现对内存管理的掌握程度。

10. 学习路径建议

要彻底掌握这类区间问题,我建议的学习路径是:

  1. 先理解基础的双指针概念(如合并两个有序数组)
  2. 练习简单的区间问题(如合并区间)
  3. 解决本题(区间交集)
  4. 尝试更复杂的变种(如区间并集、区间覆盖等)
  5. 在实际项目中寻找应用场景

LeetCode上有一个完整的区间问题合集,按难度排序,非常适合系统性地练习。我个人的经验是,至少要做10道左右的区间问题,才能对各种边界条件形成条件反射。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/18 4:02:20

从零拼出你的第一块数据大屏:DigitalTwinScreen 上手全记录

从零拼出你的第一块数据大屏&#xff1a;DigitalTwinScreen 上手全记录 【免费下载链接】DigitalTwinScreen 数字孪生可视化3d建模大屏&#xff0c;echarts,vue,cezium 项目地址: https://gitcode.com/gh_mirrors/di/DigitalTwinScreen 很多人在第一次接触"可视化大…

作者头像 李华
网站建设 2026/8/18 4:00:01

python的运筹学工业场景模拟第四十四篇:快递中转仓,多批次货物转运,中转仓容量限制,构建运输模型,求解转运分配。

快递中转仓多批次转运分配&#xff1a;用转运问题把"爆仓"变成"精准调度" "某电商物流区域分拨中心&#xff0c;每天要处理6个揽收点→3个中转仓→5个配送站的两级转运。早上6点~10点是到货高峰&#xff0c;3个中转仓的暂存面积瞬间被打满——仓1设计…

作者头像 李华
网站建设 2026/8/18 3:56:38

国际物流运费如何计算

国际物流运费如何计算 长*宽*高 *&#xff08;单位&#xff1a;厘米&#xff09;➗ 5000【快递】&#xff08;或者6000【海运、空运】&#xff09; 个数 * 海运单价 2.07 08/10 ygB:/ :3pm OX.mQ 复制打开抖音极速版&#xff0c;看看【沧州外贸运营/一诺的作品】国际物…

作者头像 李华
网站建设 2026/8/18 3:56:28

身体状态元素:人工个体动态建模的工程化路径

身体状态元素&#xff1a;人工个体动态建模的工程化路径摘要身体状态是人工个体生命状态维度的核心组成部分&#xff0c;描述个体在特定时间内所拥有的身体条件、变化与能力。本文基于个体元素关系工程框架&#xff0c;将身体状态从传统属性字段中抽离&#xff0c;构建为独立的…

作者头像 李华
网站建设 2026/8/18 3:53:53

基于SpringBoot的中华诗词文化交流平台的设计与实现

一、项目背景与意义中华诗词是中华优秀传统文化的瑰宝&#xff0c;承载着深厚的历史底蕴和民族精神。然而&#xff0c;在数字化、快节奏的现代社会&#xff0c;传统诗词文化的传播与交流面临着渠道单一、互动性弱、年轻群体参与度不高等挑战。因此&#xff0c;构建一个现代化的…

作者头像 李华
网站建设 2026/8/18 3:52:50

.NET高校学生管理系统开发实践与架构解析

1. 项目背景与需求分析 某某学院学生办公室作为校园管理的重要枢纽&#xff0c;长期面临着信息孤岛、流程繁琐、数据分散等典型痛点。传统的手工登记Excel表格管理模式已经无法满足现代高校对学生事务管理的需求。根据我们对国内30余所高校的调研&#xff0c;学生办公室日常工作…

作者头像 李华