LeetCode: 307. Range Sum Query - Mutable

LeetCode: 307. Range Sum Query - Mutable

题目描述

Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.

The update(i, val) function modifies nums by updating the element at index i to val.

Example:

Given nums = [1, 3, 5]

sumRange(0, 2) -> 9
update(1, 2)
sumRange(0, 2) -> 8

Note:

  1. The array is only modifiable by the update function.
  2. You may assume the number of calls to update and sumRange function is distributed evenly.

解题思路 —— 线段树(segment tree)

  1. 将给定数组扩展成满二叉树的叶子,不足的部分用 0 补足
  2. 每次更新数组时,循环更新它的祖先节点
  3. 每次查询区间时,从根节点递归向下寻找满足在指定区间内的节点

AC 代码

type NumArray struct {
    tree []int
}

func Constructor(nums []int) NumArray {
    var arr NumArray
    
    if len(nums) == 0 { return arr }
    
    // 形成满二叉树
    for len(nums)&(len(nums)-1) != 0 { 
        nums = append(nums, 0) 
    }
    
    arr.tree = make([]int, len(nums)*2)
    arr.tree[0] = -1 
    
    // 生成线段树
    for i := len(nums); i >= 1; i /= 2 {
        for j := i; j < i*2; j++{
            if j >= len(nums) {
                arr.tree[j] = nums[j-len(nums)]
            } else {
                arr.tree[j] = arr.tree[j*2] + arr.tree[j*2+1]
            }
        }
    }
    
    return arr
}


func (this *NumArray) Update(i int, val int)  {
    // 更新线段树
    for j := len(this.tree)/2 + i; j >= 1; j /= 2 {
        if j == len(this.tree)/2 + i {
            this.tree[j] = val
        } else {
            this.tree[j] = this.tree[j*2] + this.tree[j*2+1];
        }
    }

}

func min(m, n int) int {
    if m > n {
        return n
    } else {
        return m
    }
}

func max(m, n int) int {
    return (m + n) - min(m, n)
}

func (this *NumArray) SumRangeRef(i int, j int, idx int, beg int, end int) int { 
    
    // 区间 [i, j] 和 区间 [beg, end] 不相交
    if beg > j || end < i || end < beg {
        return 0
    }
    
    
    // 区间 [beg, end] 包含于区间 [i, j]
    if beg >= i && end <= j {
        return this.tree[idx]
    }
    
    ans := 0
    mid := (beg + end) / 2
    
    // 区间 [beg, mid] 和 区间 [i, j] 的交集
    l1 := max(beg, i)
    r1 := min(j, mid)
    if l1 <= r1 {
        ans += this.SumRangeRef(l1, r1, idx*2, beg, mid)
    }
    
    // 区间 [mid+1, end] 和 区间 [i, j] 的交集
    l2 := max(mid+1, i)
    r2 := min(j, end)
    if l2 <= r2 {
        ans += this.SumRangeRef(l2, r2, idx*2+1, mid+1, end)
    }
    
    return ans
}

func (this *NumArray) SumRange(i int, j int) int {
    return this.SumRangeRef(i+1, j+1, 1, 1, len(this.tree)/2)
}


/**
 * Your NumArray object will be instantiated and called as such:
 * obj := Constructor(nums);
 * obj.Update(i,val);
 * param_2 := obj.SumRange(i,j);
 */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值