Welcome to Subscribe On Youtube

307. Range Sum Query - Mutable

Description

Given an integer array nums, handle multiple queries of the following types:

  1. Update the value of an element in nums.
  2. Calculate the sum of the elements of nums between indices left and right inclusive where left <= right.

Implement the NumArray class:

  • NumArray(int[] nums) Initializes the object with the integer array nums.
  • void update(int index, int val) Updates the value of nums[index] to be val.
  • int sumRange(int left, int right) Returns the sum of the elements of nums between indices left and right inclusive (i.e. nums[left] + nums[left + 1] + ... + nums[right]).

 

Example 1:

Input
["NumArray", "sumRange", "update", "sumRange"]
[[[1, 3, 5]], [0, 2], [1, 2], [0, 2]]
Output
[null, 9, null, 8]

Explanation
NumArray numArray = new NumArray([1, 3, 5]);
numArray.sumRange(0, 2); // return 1 + 3 + 5 = 9
numArray.update(1, 2);   // nums = [1, 2, 5]
numArray.sumRange(0, 2); // return 1 + 2 + 5 = 8

 

Constraints:

  • 1 <= nums.length <= 3 * 104
  • -100 <= nums[i] <= 100
  • 0 <= index < nums.length
  • -100 <= val <= 100
  • 0 <= left <= right < nums.length
  • At most 3 * 104 calls will be made to update and sumRange.

Solutions

Binary Indexed Tree or Segment Tree.

Segment Tree: The line segment tree is a full binary tree with some additional information, such as the sum of the nodes of the subtree, or the maximum value, the minimum value, etc.

Java implementation https://algs4.cs.princeton.edu/99misc/SegmentTree.java.html

https://en.wikipedia.org/wiki/Segment_tree img

  • class BinaryIndexedTree {
        private int n;
        private int[] c;
    
        public BinaryIndexedTree(int n) {
            this.n = n;
            c = new int[n + 1];
        }
    
        public void update(int x, int delta) {
            while (x <= n) {
                c[x] += delta;
                x += x & -x;
            }
        }
    
        public int query(int x) {
            int s = 0;
            while (x > 0) {
                s += c[x];
                x -= x & -x;
            }
            return s;
        }
    }
    
    class NumArray {
        private BinaryIndexedTree tree;
    
        public NumArray(int[] nums) {
            int n = nums.length;
            tree = new BinaryIndexedTree(n);
            for (int i = 0; i < n; ++i) {
                tree.update(i + 1, nums[i]);
            }
        }
    
        public void update(int index, int val) {
            int prev = sumRange(index, index);
            tree.update(index + 1, val - prev);
        }
    
        public int sumRange(int left, int right) {
            return tree.query(right + 1) - tree.query(left);
        }
    }
    
    /**
     * Your NumArray object will be instantiated and called as such:
     * NumArray obj = new NumArray(nums);
     * obj.update(index,val);
     * int param_2 = obj.sumRange(left,right);
     */
    
  • class BinaryIndexedTree {
    public:
        int n;
        vector<int> c;
    
        BinaryIndexedTree(int _n)
            : n(_n)
            , c(_n + 1) {}
    
        void update(int x, int delta) {
            while (x <= n) {
                c[x] += delta;
                x += x & -x;
            }
        }
    
        int query(int x) {
            int s = 0;
            while (x > 0) {
                s += c[x];
                x -= x & -x;
            }
            return s;
        }
    };
    
    class NumArray {
    public:
        BinaryIndexedTree* tree;
    
        NumArray(vector<int>& nums) {
            int n = nums.size();
            tree = new BinaryIndexedTree(n);
            for (int i = 0; i < n; ++i) tree->update(i + 1, nums[i]);
        }
    
        void update(int index, int val) {
            int prev = sumRange(index, index);
            tree->update(index + 1, val - prev);
        }
    
        int sumRange(int left, int right) {
            return tree->query(right + 1) - tree->query(left);
        }
    };
    
    /**
     * Your NumArray object will be instantiated and called as such:
     * NumArray* obj = new NumArray(nums);
     * obj->update(index,val);
     * int param_2 = obj->sumRange(left,right);
     */
    
  • class BinaryIndexedTree:
        def __init__(self, n):
            self.n = n
            self.c = [0] * (n + 1)
    
        @staticmethod
        def lowbit(x):
            return x & -x
    
        def update(self, x, delta):
            while x <= self.n:
                self.c[x] += delta
                x += BinaryIndexedTree.lowbit(x)
    
        def query(self, x):
            s = 0
            while x > 0:
                s += self.c[x]
                x -= BinaryIndexedTree.lowbit(x)
            return s
    
    
    class NumArray:
        def __init__(self, nums: List[int]):
            self.tree = BinaryIndexedTree(len(nums))
            for i, v in enumerate(nums, 1):
                self.tree.update(i, v)
    
        def update(self, index: int, val: int) -> None:
            prev = self.sumRange(index, index)
            self.tree.update(index + 1, val - prev)
    
        def sumRange(self, left: int, right: int) -> int:
            return self.tree.query(right + 1) - self.tree.query(left)
    
    
    # Your NumArray object will be instantiated and called as such:
    # obj = NumArray(nums)
    # obj.update(index,val)
    # param_2 = obj.sumRange(left,right)
    
    ############
    
    # Segment tree node
    class STNode(object):
      def __init__(self, start, end):
        self.start = start
        self.end = end
        self.total = 0
        self.left = None
        self.right = None
    
    
    class SegmentedTree(object):
      def __init__(self, nums, start, end):
        self.root = self.buildTree(nums, start, end)
    
      def buildTree(self, nums, start, end):
        if start > end:
          return None
    
        if start == end:
          node = STNode(start, end)
          node.total = nums[start]
          return node
    
        mid = start + (end - start) / 2
    
        root = STNode(start, end)
        root.left = self.buildTree(nums, start, mid)
        root.right = self.buildTree(nums, mid + 1, end)
        root.total = root.left.total + root.right.total
        return root
    
      def updateVal(self, i, val):
        def updateVal(root, i, val):
          if root.start == root.end:
            root.total = val
            return val
          mid = root.start + (root.end - root.start) / 2
          if i <= mid:
            updateVal(root.left, i, val)
          else:
            updateVal(root.right, i, val)
    
          root.total = root.left.total + root.right.total
          return root.total
    
        return updateVal(self.root, i, val)
    
      def sumRange(self, i, j):
        def rangeSum(root, start, end):
          if root.start == start and root.end == end:
            return root.total
    
          mid = root.start + (root.end - root.start) / 2
          if j <= mid:
            return rangeSum(root.left, start, end)
          elif i >= mid + 1:
            return rangeSum(root.right, start, end)
          else:
            return rangeSum(root.left, start, mid) + rangeSum(root.right, mid + 1, end)
    
        return rangeSum(self.root, i, j)
    
    
    class NumArray(object):
      def __init__(self, nums):
        """
        initialize your data structure here.
        :type nums: List[int]
        """
        self.stTree = SegmentedTree(nums, 0, len(nums) - 1)
    
      def update(self, i, val):
        """
        :type i: int
        :type val: int
        :rtype: int
        """
        return self.stTree.updateVal(i, val)
    
      def sumRange(self, i, j):
        """
        sum of elements nums[i..j], inclusive.
        :type i: int
        :type j: int
        :rtype: int
        """
        return self.stTree.sumRange(i, j)
    
    # Your NumArray object will be instantiated and called as such:
    # numArray = NumArray(nums)
    # numArray.sumRange(0, 1)
    # numArray.update(1, 10)
    # numArray.sumRange(1, 2)
    
    
    
  • type BinaryIndexedTree struct {
    	n int
    	c []int
    }
    
    func newBinaryIndexedTree(n int) *BinaryIndexedTree {
    	c := make([]int, n+1)
    	return &BinaryIndexedTree{n, c}
    }
    
    func (t *BinaryIndexedTree) update(x, delta int) {
    	for ; x <= t.n; x += x & -x {
    		t.c[x] += delta
    	}
    }
    
    func (t *BinaryIndexedTree) query(x int) (s int) {
    	for ; x > 0; x -= x & -x {
    		s += t.c[x]
    	}
    	return s
    }
    
    type NumArray struct {
    	tree *BinaryIndexedTree
    }
    
    func Constructor(nums []int) NumArray {
    	tree := newBinaryIndexedTree(len(nums))
    	for i, v := range nums {
    		tree.update(i+1, v)
    	}
    	return NumArray{tree}
    }
    
    func (t *NumArray) Update(index int, val int) {
    	prev := t.SumRange(index, index)
    	t.tree.update(index+1, val-prev)
    }
    
    func (t *NumArray) SumRange(left int, right int) int {
    	return t.tree.query(right+1) - t.tree.query(left)
    }
    
    /**
     * Your NumArray object will be instantiated and called as such:
     * obj := Constructor(nums);
     * obj.Update(index,val);
     * param_2 := obj.SumRange(left,right);
     */
    
  • class BinaryIndexedTree {
        private n: number;
        private c: number[];
    
        constructor(n: number) {
            this.n = n;
            this.c = Array(n + 1).fill(0);
        }
    
        update(x: number, delta: number): void {
            while (x <= this.n) {
                this.c[x] += delta;
                x += x & -x;
            }
        }
    
        query(x: number): number {
            let s = 0;
            while (x > 0) {
                s += this.c[x];
                x -= x & -x;
            }
            return s;
        }
    }
    
    class NumArray {
        private tree: BinaryIndexedTree;
    
        constructor(nums: number[]) {
            const n = nums.length;
            this.tree = new BinaryIndexedTree(n);
            for (let i = 0; i < n; ++i) {
                this.tree.update(i + 1, nums[i]);
            }
        }
    
        update(index: number, val: number): void {
            const prev = this.sumRange(index, index);
            this.tree.update(index + 1, val - prev);
        }
    
        sumRange(left: number, right: number): number {
            return this.tree.query(right + 1) - this.tree.query(left);
        }
    }
    
    /**
     * Your NumArray object will be instantiated and called as such:
     * var obj = new NumArray(nums)
     * obj.update(index,val)
     * var param_2 = obj.sumRange(left,right)
     */
    
    
  • class BinaryIndexedTree {
        private int n;
        private int[] c;
    
        public BinaryIndexedTree(int n) {
            this.n = n;
            c = new int[n + 1];
        }
    
        public void Update(int x, int delta) {
            while (x <= n) {
                c[x] += delta;
                x += x & -x;
            }
        }
    
        public int Query(int x) {
            int s = 0;
            while (x > 0) {
                s += c[x];
                x -= x & -x;
            }
            return s;
        }
    }
    
    public class NumArray {
        private BinaryIndexedTree tree;
    
        public NumArray(int[] nums) {
            int n = nums.Length;
            tree = new BinaryIndexedTree(n);
            for (int i = 0; i < n; ++i) {
                tree.Update(i + 1, nums[i]);
            }
        }
    
        public void Update(int index, int val) {
            int prev = SumRange(index, index);
            tree.Update(index + 1, val - prev);
        }
    
        public int SumRange(int left, int right) {
            return tree.Query(right + 1) - tree.Query(left);
        }
    }
    
    /**
     * Your NumArray object will be instantiated and called as such:
     * NumArray obj = new NumArray(nums);
     * obj.Update(index,val);
     * int param_2 = obj.SumRange(left,right);
     */
    

All Problems

All Solutions