【leetCode】区间和检索-数组可修改

问题描述:
在这里插入图片描述
这个你就可以看出这个问题就是很简单的数组修改以及数组求和问题,但是刚刚接触算法的我,也只会暴力,就是每次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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值