【LeetCode每日一题】56. 合并区间

每日一题

2025.8.20

56. 合并区间

题目

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

示例 1:

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]

输出:[[1,6],[8,10],[15,18]]

解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

示例 2:

输入:intervals = [[1,4],[4,5]]

输出:[[1,5]]

解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。

提示:

1 <= intervals.length <= 104

intervals[i].length == 2

0 <= starti <= endi <= 104

总体思路

按起点升序(若起点相同则按终点升序)对区间排序。

这样做后,所有可能与某区间重叠的区间都会紧跟在它后面出现,便于线性扫描合并。

用一个变量 current 表示正在合并中的区间(初始化为排序后第一个)。

从左到右依次遍历后续区间 iv:

  • 若 iv.start <= current.end,说明重叠/相邻(如 [1,4] 与 [4,5] 也要合并),更新:
    current.end = max(current.end, iv.end)
  • 否则,说明没有重叠:把 current 推入结果数组,然后把 iv 设为新的 current。

扫描结束后,把最后一个 current 推入结果,完成合并。

时间复杂度:排序 O(n log n),扫描 O(n),总 O(n log n)

空间复杂度:结果需要 O(k)(k 为合并后区间数);除结果外只用到常数级额外空间。

代码

golang

go 复制代码
// merge 合并所有重叠(或相邻)的区间。
// 输入输出均为 [][]int,其中每个区间为 [start, end]。
func merge(intervals [][]int) [][]int {
	// 1) 特判:空输入或只有一个区间,直接返回
	if len(intervals) <= 1 {
		return intervals
	}

	// 2) 按起点升序排序;若起点相等,按终点升序
	// sort.Slice 使用匿名比较函数,i、j 是索引,返回 true 表示 i 应排在 j 前面
	sort.Slice(intervals, func(i, j int) bool {
		if intervals[i][0] == intervals[j][0] {
			return intervals[i][1] < intervals[j][1]
            // 如果起点一样,就比较终点
		}
        // 否则,谁的起点小谁排前
		return intervals[i][0] < intervals[j][0]
	})

	// 3) 准备结果切片。预分配容量可小优化:最多就是 n 个
	res := make([][]int, 0, len(intervals))

	// 4) current 表示当前正在合并的区间(直接引用排序后的第一个)
	current := intervals[0]   //(current[0],current[1])当前正在合并的区间

	// 5) 线性扫描其余区间
	for i := 1; i < len(intervals); i++ {
		iv := intervals[i]

		// 判断是否重叠/相邻:只要下一个区间的起点 <= 当前区间的终点
		if iv[0] <= current[1] {
			// 可以合并:更新 current 的右端点为更大的那个
			if iv[1] > current[1] {
				current[1] = iv[1]
			}
			// 注意:不立即放入 res,继续尝试与后面的区间合并
		} else {
			// 不重叠:把当前合并结果推入 res,并开始新的 current
			//current := intervals[0] // 当前正在合并的区间
            //iv := intervals[i]      // 循环里取出来的一个新区间
			res = append(res, current)
			current = iv
		}
	}

	// 6) 别忘了把最后一个合并完成的区间放进去
	res = append(res, current)

	return res
}
go 复制代码
//无注释代码纯享
func merge(intervals [][]int) [][]int {
    if len(intervals) <= 1 {
        return intervals
    }
    sort.Slice(intervals,func(i, j int) bool {
        if intervals[i][0] == intervals[j][0] {
            return intervals[i][1] < intervals[j][1]
        }
        return intervals[i][0] < intervals[j][0]
    })
    res := make([][]int, 0, len(intervals))
    current := intervals[0]
    for i:=0; i<len(intervals); i++ {
        iv := intervals[i]
        if iv[0] <= current[1] {
            if iv[1] > current[1] {
                current[1] = iv[1]
            }
        }else{
            res = append(res,current)
            current = iv
        }
    }
    res = append(res, current)
    return res
}

golang知识

  • sort.Slice 是什么?

Go 标准库里有个 sort 包,可以帮我们对切片(slice)进行排序。

它的常用函数有:

sort.Ints([]int) ------ 排序一维整型切片

sort.Strings([]string) ------ 排序字符串切片

sort.Slice(slice, lessFunc) ------ 最通用的,用来自定义规则排序任意切片。

  • sort.Slice 的用法

它的函数签名大概是:

go 复制代码
func Slice(slice interface{}, less func(i, j int) bool)

第一个参数:你要排序的切片(任何类型的都可以)

第二个参数:一个比较函数,形式是 func(i, j int) bool

i、j 是切片里的索引

返回值 true 表示:切片的第 i 个元素应该排在第 j 个元素前面

make([][]int, 0, len(intervals)) 的三个参数

make(类型, 长度, 容量)

类型:[][]int

表示"切片的元素是 []int(区间),所以它是区间的列表"。

举例:[[1,3],[2,6]] 就是 [][]int。

长度:0

说明一开始里面没有任何元素(空切片)。

容量:len(intervals)

这里表示"预留容量 = 区间总数"。

因为最多结果里不会超过输入的数量(比如 4 个区间,合并后最多还是 4 个,不会更多)。

这样预先分配好空间,可以避免 append 时底层数组频繁扩容,稍微提高效率。

相关推荐
焊锡与代码齐飞35 分钟前
嵌入式第三十五课!!Linux下的网络编程
linux·运维·服务器·开发语言·网络·学习·算法
省四收割者1 小时前
Go语言入门(10)-数组
数据结构·经验分享·笔记·vscode·算法·golang
lxmyzzs1 小时前
【图像算法 - 21】慧眼识虫:基于深度学习与OpenCV的农田害虫智能识别系统
人工智能·深度学习·opencv·算法·yolo·目标检测·计算机视觉
KeithTsui1 小时前
GCC C语言整数转换的理解(Understanding of Integer Conversions in C with GCC)
c语言·开发语言·算法
欧阳小猜3 小时前
深度学习②【优化算法(重点!)、数据获取与模型训练全解析】
人工智能·深度学习·算法
小欣加油3 小时前
leetcode 904 水果成篮
c++·算法·leetcode
有Li4 小时前
CXR-LT 2024:一场关于基于胸部X线的长尾、多标签和零样本疾病分类的MICCAI挑战赛|文献速递-深度学习人工智能医疗图像
论文阅读·人工智能·算法·医学生
墩墩同学4 小时前
【LeetCode题解】LeetCode 287. 寻找重复数
算法·leetcode·二分查找
Elieal4 小时前
Java 链表完全指南:从基础到力扣简单题实战
java·leetcode·链表