LeetCode—307. 区域和检索 - 数组可修改

307. 区域和检索 - 数组可修改

题目描述:
给你一个数组 nums ,请你完成两类查询。

其中一类查询要求 更新 数组 nums 下标对应的值
另一类查询要求返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 和 ,其中 left <= right
实现 NumArray 类:

NumArray(int[] nums) 用整数数组 nums 初始化对象
void update(int index, int val) 将 nums[index] 的值 更新 为 val
int sumRange(int left, int right) 返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 和 (即,nums[left] + nums[left + 1], …, nums[right])
在这里插入图片描述

考察重点:可以直接以数组记录每个索引点的数组和,也可以使用线段树的数组形式进行存储。二者运行时间分别为:
在这里插入图片描述
数组索引

type NumArray struct {
    nums []int
    sum []int
}


func Constructor(nums []int) NumArray {
    sum := make([]int, len(nums))
    sum[0] = nums[0]
    for i := 1;i < len(nums);i ++{
        sum[i] = sum[i-1] + nums[i] 
    }
    return NumArray{nums: nums, sum: sum}
}


func (this *NumArray) Update(index int, val int)  {
    temp := this.nums[index] - val
    for i := index;i < len(this.nums);i ++{
        this.sum[i] -= temp
    }
    this.nums[index] = val
}


func (this *NumArray) SumRange(left int, right int) int {
    if left == 0{
        return this.sum[right]
    }
    return this.sum[right] - this.sum[left-1]
}

线段树

type NumArray1 struct {
	trees []int
	nLen  int
}

/**
	偶数个:1,2,3,4
		10
	3		7
   1 2     3 4
	奇数个:1,2,3
		6
	  1   5
	     2 3
	可以发现叶节点比内部节点多1,所以n-(2n-1)存放叶节点,1-(n-1)存放内部节点
*/
func Constructor11(nums []int) NumArray1 {
	nLen := len(nums)
	trees := make([]int, 2*nLen)           //构建2*n的空间来存放线段树
	for i, j := nLen, 0; i < 2*nLen; i++ { //n 到 2n-1用来存放原数组(叶节点)
		trees[i] = nums[j]
		j++
	}
	for i := nLen - 1; i > 0; i-- { // n-1 到 0 用来存放左右节点和
		trees[i] = trees[2*i] + trees[2*i+1]
	}
	return NumArray1{trees: trees, nLen: nLen}
}

func (tt *NumArray1) Update(index int, val int) {
	index = index + tt.nLen //index存放在index + n位置上
	tt.trees[index] = val
	for index > 0 { //依次更新所有父节点的值
		right, left := index, index
		if index%2 == 0 { //为零说明index在左子树,right++,否则left--;left和right分别在index/2的左右两边
			right = index + 1
		} else {
			left = index - 1
		}
		tt.trees[index/2] = tt.trees[right] + tt.trees[left]
		index /= 2
	}
}

func (tt *NumArray1) SumRange(left int, right int) int {
	// get leaf with value 'l'
	left += tt.nLen
	// get leaf with value 'r'
	right += tt.nLen
	sum := 0
	for left <= right {
		if (left % 2) == 1 { //如果left是右子树,则只加当前left,不再由这个left向其父节点延伸
			sum += tt.trees[left]
			left++
		}
		if (right % 2) == 0 { //如果right是左子树,则只加当前right,不再由这个right向其父节点延伸
			sum += tt.trees[right]
			right--
		}
		left /= 2
		right /= 2
	}
	return sum
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ostrich5yw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值