数据结构之线段树
线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为。
而未优化的空间复杂度为2N
,实际应用时一般还要开4N
的数组以免越界,因此有时需要离散化让空间压缩。
线段树 是著名的用于高效求解 「区间问题」 的数据结构。「区间问题」即对于输入数组nums, 在其上执行 「区间求和」 、「区间修改」 等操作,通常还伴随着针对单个元素的 「单点查询」 、 「单点修改」 这两种单点操作。 若直接操作 nums ,则单点操作时间复杂度为 O(1) ,而区间操作为 O(n) ;若采用「前缀和」,则区间操作为 O(1) , 而单点操作为 O(n) 。利用完全二叉树下标特点 (静态堆式线段树) 或动态开点操作 (动态线段树), 将 nums 上对任意元素值或任意区间值 (区间求和、区间最值等) 的求解,构建在一棵二叉树上, 通过对该二叉树的分治处理 (dfs) ,同时实现 O(logn)时间复杂度的单点操作与区间操作 。
数组 -> 基本树状数组 (PURQ BIT
) -> 线段树 (Segment Tree
)
线段树相比基本树状数组,能够支持的操作种类更多,因此对一般的序列区间问题更具 普适性 。
基本线段树
基本线段树只支持 「单点修改」 和 「区间查询」 的功能。
构建基本线段树
线段树的基本结构就是二叉树,需要将数组每个元素都放在二叉树的叶子节点上, 而它们的父节点都是其所有叶子节点的和,即这个数组的区间和。所以,其根节点就是数组的和。
假设有一个数组 arr = [2,3,4,5,6,7]
,其转化为线段树之后的结构如下图所 示:
其中, dp 即为构建的线段树,其在代码里表现为数组形式。
通过观察,可以发现 dp 的下标是有规律的, dp[i] 的左子节点是 dp[] 右子节点是 dp[ + 1]。
如果 dp[i] 代表的是数组 arr[s, t] 的区间的话,那其左子节点是 ,右子节点是