静态区间合并无需线段树,排序加单次遍历即可完成;应先按左端点升序排序,再遍历维护当前合并段,注意空输入、单区间及右端点取max。

线段树在 Go 中不适合做普通区间合并
普通区间合并(如 [[1,3],[2,6],[8,10]] → [[1,6],[8,10]])根本不需要线段树。直接排序 + 一次遍历就能完成,时间复杂度 O(n log n),代码不到 15 行。线段树是为「动态区间操作」设计的,比如边插入边查重叠、频繁修改某段值、统计区间内满足条件的元素个数等。用它处理静态合并,纯属杀鸡用牛刀,还容易写错边界。
Go 实现静态区间合并只需 sort.Slice 和 for 循环
核心逻辑:按左端点升序排序,维护当前合并段 current,逐个判断是否能接上。注意两个易错点:空输入、单区间、右端点取 max 而非直接覆盖。
func merge(intervals [][]int) [][]int {
if len(intervals)
-
max需自己定义或用int(math.Max(float64(a), float64(b))),Go 标准库无泛型max - 切片追加时不要用
res = append(res, []int{current[0], current[1]})—— 这会新建底层数组,浪费内存 - 输入含负数?没问题,排序和比较逻辑完全不变
真要用线段树,优先选动态开点而非数组堆式
Go 没有指针算术,数组堆式线段树(tree[2*idx], tree[2*idx+1])容易越界且难以调试;动态开点用结构体 + 指针更自然,内存按需分配,也方便支持懒标记(lazy propagation)。
type Node struct {
left, right int
sum int
lazy int
lChild, rChild *Node
}
- 每次
update或query前检查子节点是否存在,不存在则新建:if node.lChild == nil { node.lChild = newNode(l, mid) } - 区间更新必须下推
lazy,否则查询结果错误——这是 90% 的 Go 线段树 bug 来源 - 别存
[l,r]为闭区间还是左闭右开,全程统一。推荐闭区间,和多数算法题输入格式一致
查询重叠区间用扫描线比线段树更简单可靠
如果实际需求是「给定新区间 [a,b],查出所有与之重叠的已存区间」,线段树反而绕路。直接用扫描线(sweep line)+ sort.Search 二分即可:
- 把所有区间的左、右端点分别存进两个切片
lefts,rights,并排序 - 用
sort.Search找第一个lefts[i] ,再找第一个 <code>rights[j] >= a - 重叠区间索引范围就是这两个位置的交集
- 若数据不常变,还可预建
map[int][]int把每个坐标映射到覆盖它的区间 ID 列表,O(1)查询
线段树真正的价值场景只有一个:数据持续增删改,且每次操作都依赖历史状态(比如区间赋值后立刻查最大值)。其他情况,先想清楚是不是被“高级数据结构”这个词唬住了。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











