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

Method 1 Segment Tree

  • """ The idea here is to build a segment tree. Each node stores the left and right endpoint of an interval and the sum of that interval. All of the leaves will store elements of the array and each internal node will store sum of leaves under it. Creating the tree takes O(n) time. Query and updates are both O(log n). """
  • In Computer science, a segment tree is a tree data structure used for storing information about intervals, or segments. It allows querying which of the stored segments contain a given point. A segment tree for a set I of n intervals uses O(n log n) storage and can be built in O(n log n) time. Segment trees support searching for all the intervals that contain a query point in O(log n + k), k being the number of retrieved intervals or segments.[1]
class Node(object):

    def __init__(self, start, end, total):
        self.left = None
        self.right = None
        self.total = total
        self.start = start
        self.end = end

class NumArray(object):

    def __init__(self, nums):
        """
        :type nums: List[int]
        """

        # O(n) time
        def createTree(start, end):
            if start > end:
                return None
            # leaf node
            if start == end:
                n = Node(start, end, nums[start])
                return n

            mid = (start + end) / 2
            root = Node(start, end, 0)

            #recursively build the Segment tree
            root.left = createTree(start, mid)
            root.right = createTree(mid+1, end)

            #Total stores the sum of all leaves under root
            #i.e. those elements lying between (start, end)
            root.total = root.left.total + root.right.total

            return root
        self.root = createTree(0, len(nums)-1)

    def update(self, i, val): 

        # O(log n) time
        def updateTree(root):
            if root.start == root.end:
                root.total = val
                return 

            mid = (root.start + root.end) / 2
            #If the index is less than the mid, that leaf must be in the left subtree
            if i > mid:
                updateTree(root.right)
            else:
                updateTree(root.left)
             #Propogate the changes after recursive call returns
            root.total = root.left.total + root.right.total

        updateTree(self.root)


    def sumRange(self, i, j):

        def findRange(root, start, end):
            #If the range exactly matches the root, we already have the sum
            if root.start == start and root.end == end:
                return root.total

            mid = (root.start + root.end) / 2
            #If end of the range is less than the mid, the entire interval lies #in the left subtree
            if end <= mid:
                return findRange(root.left, start, end)
            #If start of the interval is greater than mid, the entire inteval lies
            #in the right subtree
            elif start >= mid + 1:
                return findRange(root.right, start, end)            
            #Otherwise, the interval is split. So we calculate the sum recursively,
            #by splitting the interval
            else:
                return findRange(root.left, start, mid) +  findRange(root.right, mid+1, end)

        return findRange(self.root, i , j)

results matching ""

    No results matching ""