Leetcode: Range Sum Query - Mutable && Summary: Segment Tree
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: The array is only modifiable by the update function. You may assume the number of calls to update and sumRange function is distributed evenly.
Introduction of Segment Tree: http://www.geeksforgeeks.org/segment-tree-set-1-sum-of-given-range/
Time Complexity:
Time Complexity for tree construction is O(n). There are total 2n-1 nodes, and value of every node is calculated only once in tree construction.
Time complexity to query is O(Logn). To query a sum, we process at most four nodes at every level and number of levels is O(Logn).
The time complexity of update is also O(Logn). To update a leaf value, we process one node at every level and number of levels is O(Logn).
1 public class NumArray { 2 SegmentTreeNode root; 3 4 public NumArray(int[] nums) { 5 this.root = buildTree(nums, 0, nums.length-1); 6 } 7 8 void update(int i, int val) { 9 update(root, i, val); 10 } 11 12 public int sumRange(int i, int j) { 13 return sumRange(root, i, j); 14 } 15 16 public SegmentTreeNode buildTree(int[] nums, int start, int end) { 17 if (start > end) return null; 18 else { 19 SegmentTreeNode cur = new SegmentTreeNode(start, end); 20 if (start == end) { 21 cur.sum = nums[start]; 22 } 23 else { 24 int mid = start + (end - start)/2; 25 cur.left = buildTree(nums, start, mid); 26 cur.right = buildTree(nums, mid+1, end); 27 cur.sum = cur.left.sum + cur.right.sum; 28 } 29 return cur; 30 } 31 } 32 33 public void update(SegmentTreeNode root, int i, int val) { 34 if (root.start == root.end) { //leaf node 35 root.sum = val; 36 return; 37 } 38 else { 39 int mid = root.start + (root.end - root.start)/2; 40 if (i <= mid) update(root.left, i, val); 41 else update(root.right, i, val); 42 root.sum = root.left.sum + root.right.sum; 43 } 44 } 45 46 public int sumRange(SegmentTreeNode root, int i, int j) { 47 if (i==root.start && j==root.end) return root.sum; 48 else { 49 int mid = root.start + (root.end - root.start)/2; 50 if (j <= mid) return sumRange(root.left, i, j); 51 else if (i >= mid+1) return sumRange(root.right, i, j); 52 else 53 return sumRange(root.left, i, mid) + sumRange(root.right, mid+1, j); 54 } 55 } 56 57 58 public class SegmentTreeNode{ 59 int sum; 60 int start; 61 int end; 62 SegmentTreeNode left; 63 SegmentTreeNode right; 64 65 public SegmentTreeNode(int start, int end) { 66 this.sum = 0; 67 this.start = start; 68 this.end = end; 69 this.left = null; 70 this.right = null; 71 } 72 73 } 74 } 75 76 77 // Your NumArray object will be instantiated and called as such: 78 // NumArray numArray = new NumArray(nums); 79 // numArray.sumRange(0, 1); 80 // numArray.update(1, 10); 81 // numArray.sumRange(1, 2);