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.
思路:
线段树
1. 将给定数组的信息转到线段树。 用recursion来build tree
2. 在建好的线段树上进行sumRange()操作, 时间复杂度为O(logn)
3. 在建好的线段树上进行update()操作, 时间复杂度为O(logn)
代码
1 class NumArray { 2 private SegmentTreeNode root; 3 /*Time Complexity: O(n) 4 Build SegmentTree 5 */ 6 public NumArray (int[] nums) { 7 this.root = buildTree(nums, 0, nums.length - 1); 8 } 9 private SegmentTreeNode buildTree(int[] nums, int start, int end) { 10 if (start > end) return null; 11 SegmentTreeNode node = new SegmentTreeNode(start, end); 12 if (start == end) { 13 node.val = nums[start]; 14 } else { 15 int mid = start + (end - start) / 2; 16 node.left = buildTree(nums, start, mid); 17 node.right = buildTree(nums, mid + 1, end); 18 node.val = node.left.val + node.right.val; 19 } 20 return node; 21 } 22 /* Time Complexity: O(log n) 23 update() 24 */ 25 public void update(int i, int val) { 26 update(this.root, i, val); 27 } 28 void update(SegmentTreeNode root, int i, int val) { 29 if (root.start == root.end) { 30 root.val = val; 31 return; 32 } 33 int middle = root.start + (root.end - root.start) / 2; 34 if (i <= middle) { 35 update(root.left, i, val); 36 } else { 37 update(root.right, i, val); 38 } 39 root.val = root.left.val + root.right.val; 40 } 41 /* Time Complexity: O(log n) 42 sumRange() 43 */ 44 public int sumRange(int i, int j) { 45 return sumRange(this.root, i, j); 46 } 47 int sumRange(SegmentTreeNode root, int start, int end) { 48 if (root.end == end && root.start == start) return root.val; 49 int mid = root.start + (root.end - root.start) / 2; 50 if (end <= mid) { 51 return sumRange(root.left, start, end); 52 } else if (start >= mid + 1) { 53 return sumRange(root.right, start, end); 54 } else { 55 return sumRange(root.right, mid + 1, end) + sumRange(root.left, start, mid); 56 } 57 } 58 59 class SegmentTreeNode { 60 int start; 61 int end; 62 int val; 63 SegmentTreeNode left; 64 SegmentTreeNode right; 65 66 public SegmentTreeNode(int start, int end) { 67 this.start = start; 68 this.end = end; 69 this.val = 0; 70 } 71 } 72 }