【leetcode】307. Range Sum Query - Mutable

题目如下:

解题思路:就三个字-线段树。这个题目是线段树用法最经典的场景。

代码如下:

class NumArray(object):

    def __init__(self, nums):
        """
        :type nums: List[int]
        """
        self.nl = nums
        self.tree = []
        if len(nums) == 0:
            return
        for i in xrange((4*len(nums)+1)):
            self.tree.append([])
        self.build(1,len(nums),1,nums)
        #print self.tree


    def build(self,l,r,k,nums):
        self.tree[k] = [l,r]
        if l == r: #leaf
            self.tree[k].append(nums[l-1])
            return nums[l-1]
        wl = self.build(l,(l+r)/2,2*k,nums)
        wr = self.build((l+r)/2+1,r,2*k+1,nums)
        #print l,r,wl,wr
        self.tree[k].append(wl+wr)
        return self.tree[k][2]

    def update(self, i, val):
        """
        :type i: int
        :type val: int
        :rtype: void
        """
        if i > len(self.nl):
            return
        diff = self.nl[i] - val
        #for j in range(i,len(self.sl)):
        #    self.sl[j] -= diff
        self.nl[i] = val
        k = 1
        i += 1
        while True:
            self.tree[k][2] -= diff
            m = (self.tree[k][0] + self.tree[k][1])/2
            if self.tree[k][0] == self.tree[k][1]:
                break
            if i <= m:
                k = 2*k
            else:
                k = 2*k + 1

        #print self.tree

    def calcRange(self,i,j,k):
        #print i,j,k
        if i == self.tree[k][0] and j == self.tree[k][1]:
            return self.tree[k][2]
        m = (self.tree[k][0] + self.tree[k][1])/2
        if j <= m:
            return self.calcRange(i,j,2*k)
        elif i > m:
            return self.calcRange(i,j,2*k+1)
        else:
            return self.calcRange(i,m,2*k) + self.calcRange(m+1,j,2*k+1)

    def sumRange(self, i, j):
        """
        :type i: int
        :type j: int
        :rtype: int
        """
        #print self.sl
        #print self.nl
        return self.calcRange(i+1,j+1,1)
        


# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# obj.update(i,val)
# param_2 = obj.sumRange(i,j)

 

posted @ 2018-06-22 13:24  seyjs  阅读(142)  评论(0编辑  收藏  举报