Given an integer array nums
, and then you need to implement two functions:
update(i, val)
Modify the element whose index is i to val.sumRange(l, r)
Return the sum of elements whose indexes are in range of [l, r][l,r].
Example
Example 1:
Input:
nums = [1, 3, 5]
sumRange(0, 2)
update(1, 2)
sumRange(0, 2)
Output:
9
8
Example 2:
Input:
nums = [0, 9, 5, 7, 3]
sumRange(4, 4)
sumRange(2, 4)
update(4, 5)
update(1, 7)
update(0, 8)
sumRange(1, 2)
Output:
3
15
12
Notice
- The array is only modifiable by the update function.
- You may assume the number of calls to update and sumRange function is distributed evenly.
思路:用segment tree,可以直接用array build tree,然后每个index modify成(i, nums[i]),然后按照模板写出segment tree即可;Time Build Tree O(N), query , modify O(logN).
class NumArray {
private SegmentTree tree;
public NumArray(int[] nums) {
tree = new SegmentTree(nums);
}
public void update(int i, int val) {
tree.modify(i, val);
}
public int sumRange(int i, int j) {
return tree.querySum(i, j);
}
private class SegmentTreeNode {
public int start, end;
public int sum;
public SegmentTreeNode left, right;
public SegmentTreeNode (int start, int end) {
this.start = start;
this.end = end;
}
}
private class SegmentTree {
public SegmentTreeNode root;
public int size;
public SegmentTree(int[] A) {
this.size = A.length;
this.root = buildTree(A, 0, size - 1);
}
private SegmentTreeNode buildTree(int[] A, int start, int end) {
if(start > end) {
return null;
}
SegmentTreeNode root = new SegmentTreeNode(start, end);
if(start == end) {
root.sum = A[start];
return root;
}
int mid = start + (end - start) / 2;
root.left = buildTree(A, start, mid);
root.right = buildTree(A, mid + 1, end);
root.sum = root.left.sum + root.right.sum;
return root;
}
private int querySum(SegmentTreeNode root, int start, int end) {
if(root.start == start && root.end == end) {
return root.sum;
}
int mid = root.start + (root.end - root.start) / 2;
int leftsum = 0, rightsum = 0;
if(start <= mid) {
leftsum = querySum(root.left, start, Math.min(mid, end));
}
if(end >= mid + 1) {
rightsum = querySum(root.right, Math.max(start, mid + 1), end);
}
return leftsum + rightsum;
}
private void modify(SegmentTreeNode root, int index, int value) {
if(root.start == root.end && root.end == index) {
root.sum = value;
return;
}
int mid = root.start + (root.end - root.start) / 2;
if(index <= mid) {
modify(root.left, index, value);
} else {
modify(root.right, index, value);
}
root.sum = root.left.sum + root.right.sum;
}
public int querySum(int start, int end) {
return querySum(root, start, end);
}
public void modify(int index, int value) {
modify(root, index, value);
}
}
}
/**
* Your NumArray object will be instantiated and called as such:
* NumArray obj = new NumArray(nums);
* obj.update(i,val);
* int param_2 = obj.sumRange(i,j);
*/