问题描述:
这个你就可以看出这个问题就是很简单的数组修改以及数组求和问题,但是刚刚接触算法的我,也只会暴力,就是每次for循环进行求解。
看了题解之后知道有前缀和、线段树、树状数组三类,写了一下用前缀和去求解这个问题的代码,但是不是最终答案。
首先解释下,前缀和是什么意思,就是先提前建立数组保存在这个数之前所有数的和。
class NumArray:
def __init__(self, nums: List[int]):
self.nums =nums
self.prefix_sum = [] #用于保存某个元素之前所有元素的和
for i in range(0,len(self.nums)):
if i ==0:
self.prefix_sum.append(self.nums[0])
else:
self.prefix_sum.append(self.prefix_sum[i-1]+self.nums[i])
def update(self, index: int, val: int) -> None:
delta = val-self.nums[index]
self.nums[index]=val
for i in range(index,len(self.nums)):
self.prefix_sum[i] += delta
def sumRange(self, left: int, right: int) -> int:
return self.prefix_sum[right]-self.prefix_sum[left]+self.nums[left]
当然解法还是超出时间。
这道题的解法应该是用线段树解法,线段树是什么意思,是一种二叉搜索树,每个结点至多两颗子树。
类似二分,图上的应该是属于求出该区间内的最大值,但是我们这道题求的是区间内的和,所以这里应该把结点值改成区间和。
class NumArray:
def __init__(self, nums: List[int]):
n = len(nums)
self.n = n #数组长度
self.seg = [0] * (n * 4) #
self.build(nums, 0, 0, n - 1) #建立线段树
def build(self, nums: List[int], node: int, s: int, e: int):
if s == e: #如果左右结点的索引大小一样的话,说明是本身,直接赋值
self.seg[node] = nums[s]
return
m = s + (e - s) // 2 #二分,分为左右子树
self.build(nums, node * 2 + 1, s, m) #建左子树
self.build(nums, node * 2 + 2, m + 1, e) #建右子树
self.seg[node] = self.seg[node * 2 + 1] + self.seg[node * 2 + 2] #所以结点的值为左右子树的和
def change(self, index: int, val: int, node: int, s: int, e: int): #单点值改,与该点相关的所有值都要改
if s == e:
self.seg[node] = val
return
m = s + (e - s) // 2
if index <= m:
self.change(index, val, node * 2 + 1, s, m)
else:
self.change(index, val, node * 2 + 2, m + 1, e)
self.seg[node] = self.seg[node * 2 + 1] + self.seg[node * 2 + 2]
def range(self, left: int, right: int, node: int, s: int, e: int) -> int:
if left == s and right == e:
return self.seg[node]
m = s + (e - s) // 2
if right <= m:
return self.range(left, right, node * 2 + 1, s, m)
if left > m:
return self.range(left, right, node * 2 + 2, m + 1, e)
return self.range(left, m, node * 2 + 1, s, m) + self.range(m + 1, right, node * 2 + 2, m + 1, e)
def update(self, index: int, val: int) -> None:
self.change(index, val, 0, 0, self.n - 1)
def sumRange(self, left: int, right: int) -> int:
return self.range(left, right, 0, 0, self.n - 1)