Leetcode-307Range 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.

My Solution:

class Segment_tree:
    def build_Segment_tree(self, pos, left, right, value, nums):
        if left == right:
            value[pos] = nums[left]
            return
        mid = (left + right) // 2
        self.build_Segment_tree(2 * pos + 1, left, mid, value, nums)
        self.build_Segment_tree(2 * pos + 2, mid + 1, right, value, nums)
        value[pos] = value[2 * pos + 1] + value[2 * pos + 2]

    def sumRange_Segment_tree(self, pos, left, right, qleft, qright, value, nums):

        if qleft <= left and qright >= right:  # 区间被[qleft, qright]所覆盖
            return value[pos]
        if qleft > right or qright < left:
            return 0
        mid = (left + right) // 2
        return self.sumRange_Segment_tree(pos * 2 + 1, left, mid, qleft, qright, value, nums) + self.sumRange_Segment_tree(pos * 2 + 2, mid + 1, right, qleft, qright, value, nums)
    
    def update__Segment_tree(self, pos, i, left, right, value, val, nums):
        if left == right and left == i:
            # if pos == i:
            #     value[pos] = val
            # else:
            value[pos] = val
            return
        mid = (left + right) // 2
        if i <= mid:
            self.update__Segment_tree(2 * pos + 1, i, left, mid, value, val, nums)
        else:
            self.update__Segment_tree(2 * pos + 2, i, mid + 1, right, value, val, nums)
        value[pos] = value[2 * pos + 1] + value[2 * pos + 2]


class NumArray:

    def __init__(self, nums):
        """
        :type nums: List[int]
        """
        self.value = [0 for i in range(4 * len(nums))]  # 线段树通常开数组长度 n 的 4 倍空间4 * n
        self.nums = nums
        if self.nums:
            Segment_tree().build_Segment_tree(0, 0, len(nums) - 1, self.value, self.nums)

    def update(self, i, val):
        """
        :type i: int
        :type val: int
        :rtype: void
        """
        Segment_tree().update__Segment_tree(0, i, 0, len(self.nums) - 1, self.value, val, self.nums)

    def sumRange(self, i, j):
        """
        :type i: int
        :type j: int
        :rtype: int
        """
        return Segment_tree().sumRange_Segment_tree(0, 0, len(self.nums) - 1, i, j, self.value, self.nums)

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

Reference 1:

说明:

Use self.c to represent Binary Indexed Tree.
Section sums are stored in self.c[1..len(nums)]. x & -x is lowbit function,
which will return x's rightmost bit 1, e.g. lowbit(7) = 1, lowbit(20) = 4.


self.c[1] = nums[0]
self.c[2] = nums[0] + nums[1]
self.c[3] = nums[2]
self.c[4] = nums[0] + nums[1] + nums[2] + nums[3]
self.c[5] = nums[4]
self.c[6] = nums[4] + nums[5]
self.c[7] = nums[6]
self.c[8] = nums[0] + nums[1] + nums[2] + nums[3] + nums[4] + nums[5] + nums[6] + nums[7]


class NumArray(object):
    def __init__(self, nums):
        self.n = len(nums)
        self.a, self.c = nums, [0] * (self.n + 1)
        for i in range(self.n):
            k = i + 1
            while k <= self.n:
                self.c[k] += nums[i]
                k += (k & -k)

    def update(self, i, val):
        diff, self.a[i] = val - self.a[i], val
        i += 1
        while i <= self.n:
            self.c[i] += diff
            i += (i & -i)

    def sumRange(self, i, j):
        res, j = 0, j + 1
        while j:
            res += self.c[j]
            j -= (j & -j)
        while i:
            res -= self.c[i]
            i -= (i & -i)
        return res

Reference 2:

class NumArray(object):
    def __init__(self, nums):
        self.update = nums.__setitem__
        self.sumRange = lambda i, j: sum(nums[i:j+1])

你可能感兴趣的:(Leetcode-307Range Sum Query - Mutable)