0307. Range Sum Query Mutable

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.

题目大意 #

给定一个整数数组  nums,求出数组从索引 i 到 j  (i ≤ j) 范围内元素的总和,包含 i,  j 两点。

update(i, val) 函数可以通过将下标为 i 的数值更新为 val,从而对数列进行修改。

示例:

Given nums = [1, 3, 5]

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

说明:

  • 数组仅可以在 update 函数下进行修改。
  • 你可以假设 update 函数与 sumRange 函数的调用次数是均匀分布的。

解题思路 #

  • 给出一个数组,数组里面的数都是**可变**的,设计一个数据结构能够满足查询数组任意区间内元素的和。
  • 对比第 303 题,这一题由于数组里面的元素都是可变的,所以第一个想到的解法就是线段树,构建一颗线段树,父结点内存的是两个子结点的和,初始化建树的时间复杂度是 O(log n),查询区间元素和的时间复杂度是 O(log n),更新元素值的时间复杂度是 O(log n)。
  • 如果此题还用 prefixSum 的思路解答呢?那每次 update 操作的时间复杂度都是 O(n),因为每次更改一个值,最坏情况就是所有的 prefixSum 都要更新一次。prefixSum 的方法在这道题上面也可以 AC,只不过时间排名在 5%,非常差。
  • 此题也可以用树状数组解决。代码很直白,区间查询即是两个区间前缀和相减。最简单的树状数组应用。

代码 #


package leetcode

import "github.com/halfrost/leetcode-go/template"

// NumArray define
type NumArray struct {
	st *template.SegmentTree
}

// Constructor307 define
func Constructor307(nums []int) NumArray {
	st := template.SegmentTree{}
	st.Init(nums, func(i, j int) int {
		return i + j
	})
	return NumArray{st: &st}
}

// Update define
func (this *NumArray) Update(i int, val int) {
	this.st.Update(i, val)
}

// SumRange define
func (this *NumArray) SumRange(i int, j int) int {
	return this.st.Query(i, j)
}

//解法二 prefixSum,sumRange 时间复杂度 O(1)

// // NumArray define
// type NumArray307 struct {
// 	prefixSum []int
// 	data   []int
// }

// // Constructor307 define
// func Constructor307(nums []int) NumArray307 {
// 	data := make([]int, len(nums))
// 	for i := 0; i < len(nums); i++ {
// 		data[i] = nums[i]
// 	}
// 	for i := 1; i < len(nums); i++ {
// 		nums[i] += nums[i-1]
// 	}
// 	return NumArray307{prefixSum: nums, data: data}
// }

// // Update define
// func (this *NumArray307) Update(i int, val int) {
// 	this.data[i] = val
// 	this.prefixSum[0] = this.data[0]
// 	for i := 1; i < len(this.data); i++ {
// 		this.prefixSum[i] = this.prefixSum[i-1] + this.data[i]
// 	}
// }

// // SumRange define
// func (this *NumArray307) SumRange(i int, j int) int {
// 	if i > 0 {
// 		return this.prefixSum[j] - this.prefixSum[i-1]
// 	}
// 	return this.prefixSum[j]
// }

// 解法三 树状数组
// type NumArray struct {
// 	bit  template.BinaryIndexedTree
// 	data []int
// }

// // Constructor define
// func Constructor307(nums []int) NumArray {
// 	bit := template.BinaryIndexedTree{}
// 	bit.InitWithNums(nums)
// 	return NumArray{bit: bit, data: nums}
// }

// // Update define
// func (this *NumArray) Update(i int, val int) {
// 	this.bit.Add(i+1, val-this.data[i])
// 	this.data[i] = val
// }

// // SumRange define
// func (this *NumArray) SumRange(i int, j int) int {
// 	return this.bit.Query(j+1) - this.bit.Query(i)
// }

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


⬅️上一页

下一页➡️

Calendar Apr 8, 2023
Edit Edit this page
本站总访问量:  次 您是本站第  位访问者