Segment Tree, 线段树

什么是Segment Tree?

它是一个binary tree,表示每个parent只有两个children;他是平衡的(balanced binary tree),但不定是完美平衡,保证是O(logn)的高度。

它的每个叶子结点代表了数组里的每一个元素,并且还带有一个范围:start,end,如(0,1),表示数组的元素的第0和第1个。

每个非叶子结点,就是left,right两个children的值的和,同时也带有一个范围,start是left的start,end是right的end。

Segment Tree提供的操作

  • build(start,end,values),时间复杂度为O(n)
  • update(index,value),时间复杂度为O(logn)
  • rangeQuery(start,end),时间复杂度为O(logn+k),k值是会复盖到节点的数量

它的作用是什么?

Segment Tree与树状数组(Binary indexed tree)相似,也用来处理数组相应的区间查询(range queue)和元素更新(update)操作。与树状数组不同的是,线段树不止可以适用于区间求和的查询,也可以进行区间最大值,区间最小值 或者 区间异或值的查询。

代码实现

TreeNode

复制代码
class TreeNode constructor(start: Int, end: Int, sum: Int = 0) {
    var start = 0
    var end = 0
    var sum = 0
    var left:TreeNode?=null
    var right:TreeNode?=null

    init {
        this.start = start
        this.end = end
        this.sum = sum
    }
}
复制代码

 

SegmentTree

复制代码
class SegmentTree {

    fun build(nums: IntArray?, start: Int, end: Int): TreeNode? {
        if (nums == null) {
            return null
        }
        if (start == end) {
            return TreeNode(start, end, nums!![start])
        }
        val currentNode = TreeNode(start, end)
        val mid = (start + end) / 2
        currentNode.left = build(nums, start, mid)
        currentNode.right = build(nums, mid + 1, end)
        val leftSum = currentNode.left?.sum ?: 0
        val rightSum = currentNode.right?.sum ?: 0
        currentNode.sum = leftSum + rightSum
        return currentNode
    }

    fun update(node: TreeNode?, i: Int, value: Int) {
        if (node == null) {
            return
        }
        if (node.start == i && node.end == i) {
            node.sum = value
            return
        }
        val mid = (node.start + node.end) / 2
        if (i <= mid) {
            update(node.left, i, value)
        } else {
            update(node.right, i, value)
        }
        val leftSum = node.left?.sum ?: 0
        val rightSum = node.right?.sum ?: 0
        node.sum = leftSum + rightSum
    }

    fun rangeQueue(node: TreeNode?, i: Int, j: Int): Int {
        if (node == null) {
            return 0
        }
        if (i == node.start && j == node.end) {
            return node.sum
        }
        val mid = (node.start + node.end) / 2
        if (j<= mid) {
            return rangeQueue(node.left, i, j)
        } else if (i > mid) {
            return rangeQueue(node.right, i, j)
        } else {
            return rangeQueue(node.left, i, mid) + rangeQueue(node.right, mid + 1, j)
        }
    }
}
复制代码

 

Leetcode上的应用

307. Range Sum Query - Mutable

 

posted @   johnny_zhao  阅读(174)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示