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:
- The array is only modifiable by the update function.
- You may assume the number of calls to update and sumRange function is distributed evenly.
class NumArray { List<Integer> list = new ArrayList(); public NumArray(int[] nums) { for(int i: nums) list.add(i); } public void update(int i, int val) { list.set(i, val); } public int sumRange(int i, int j) { int res = 0; for(int m = i; m <= j; m++) res+=list.get(m); return res; } }
public class NumArray { class SegmentTreeNode { int start, end; SegmentTreeNode left, right; int sum; public SegmentTreeNode(int start, int end) { this.start = start; this.end = end; this.left = null; this.right = null; this.sum = 0; } } SegmentTreeNode root = null; public NumArray(int[] nums) { root = buildTree(nums, 0, nums.length-1); } private SegmentTreeNode buildTree(int[] nums, int start, int end) { if (start > end) { return null; } else { SegmentTreeNode ret = new SegmentTreeNode(start, end); if (start == end) { ret.sum = nums[start]; } else { int mid = start + (end - start) / 2; ret.left = buildTree(nums, start, mid); ret.right = buildTree(nums, mid + 1, end); ret.sum = ret.left.sum + ret.right.sum; } return ret; } } void update(int i, int val) { update(root, i, val); } void update(SegmentTreeNode root, int pos, int val) { if (root.start == root.end) { root.sum = val; } else { int mid = root.start + (root.end - root.start) / 2; if (pos <= mid) { update(root.left, pos, val); } else { update(root.right, pos, val); } root.sum = root.left.sum + root.right.sum; } } public int sumRange(int i, int j) { return sumRange(root, i, j); } public int sumRange(SegmentTreeNode root, int start, int end) { if (root.end == end && root.start == start) { return root.sum; } else { int mid = root.start + (root.end - root.start) / 2; if (end <= mid) { return sumRange(root.left, start, end); } else if (start >= mid+1) { return sumRange(root.right, start, end); } else { return sumRange(root.right, mid+1, end) + sumRange(root.left, start, mid); } } } }
Segment tree, 主要解决的是range sum,update等疑难杂症。意思是构建一个树,这个树的root是所有的sum,然后left child是左边的sum,right child是右边的sum,直到leaf node(单个数字的sum是它本身)。
Segment node里面有left,right代表左右child,start end代表这个node的sum是从哪开始,到哪结束,sum代表这一段的range sum。
build:构造的时候就像构造其他树,从mid开始,递归它的left,right,更新当前node的sum。
update:
递归结束条件是到达最底层,更新这个position的结点的值,也就是更新它的sum。上层是根据当前位置选择进入左子树还是右子树,也要跟着更新所有的sum。
sumRange:有几种可能,1)mid ≥ end,比如数组是0-9,mid就是4,如果range sum是【0,2】,那就要进入到左子树。2)mid + 1 ≤ start,【5,6】,进入右子树。3)【3,5】,左右都要进去并返回对应的。
https://blog.csdn.net/yuzhiqiang666/article/details/80643017
https://leetcode.com/problems/range-sum-query-mutable/discuss/75724/17-ms-Java-solution-with-segment-tree