原题网址:https://leetcode.com/problems/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.
方法一:分段树(Segment Tree)
public class NumArray {
private TreeNode root;
private TreeNode buildTree(int[] nums, int from, int to) {
if (from>to) return null;
TreeNode node = new TreeNode(from, to);
if (from==to) {
node.sum=nums[from];
return node;
}
int m = (from+to)/2;
node.left = buildTree(nums, from, m);
node.right = buildTree(nums, m+1, to);
node.sum = node.left.sum + node.right.sum;
return node;
}
private void updateTree(TreeNode node, int i, int val) {
if (node==null) return;
if (node.from==node.to) {
if (node.from==i) {
node.sum = val;
}
return;
}
int m = (node.from+node.to)/2;
if (i<=m) {
updateTree(node.left, i, val);
} else {
updateTree(node.right, i, val);
}
node.sum = node.left.sum + node.right.sum;
}
public NumArray(int[] nums) {
this.root = buildTree(nums, 0, nums.length-1);
}
void update(int i, int val) {
updateTree(root, i, val);
}
private int sum(TreeNode node, int i, int j) {
if (node.from == node.to) return node.sum;
if (node.from == i && node.to == j) return node.sum;
int sum = 0;
int m = (node.from+node.to)/2;
if (i<=m && j<=m) return sum(node.left, i,j);
if (i>m) return sum(node.right, i, j);
return sum(node.left, i, m) + sum(node.right, m+1, j);
}
public int sumRange(int i, int j) {
return sum(root, i, j);
}
}
class TreeNode {
int from, to;
int sum;
TreeNode left, right;
TreeNode(int from, int to) {
this.from = from;
this.to = to;
}
}
// Your NumArray object will be instantiated and called as such:
// NumArray numArray = new NumArray(nums);
// numArray.sumRange(0, 1);
// numArray.update(1, 10);
// numArray.sumRange(1, 2);
方法二:树状数组。
public class NumArray {
private int[] tree;
private int[] nums;
public NumArray(int[] nums) {
this.tree = new int[nums.length+1];
this.nums = new int[nums.length];
for(int i=0; i<nums.length; i++) update(i, nums[i]);
}
void adjust(int i, int val) {
i ++;
while (i<tree.length) {
tree[i] += val;
i += (i & -i);
}
}
void update(int i, int val) {
int adjust = val - nums[i];
nums[i] = val;
adjust(i, adjust);
}
int sum(int i) {
i ++;
int sum = 0;
while (i>0) {
sum += tree[i];
i -= (i & -i);
}
return sum;
}
public int sumRange(int i, int j) {
return sum(j)-sum(i-1);
}
}
// Your NumArray object will be instantiated and called as such:
// NumArray numArray = new NumArray(nums);
// numArray.sumRange(0, 1);
// numArray.update(1, 10);
// numArray.sumRange(1, 2);
参考文章:
https://leetcode.com/discuss/74222/java-using-binary-indexed-tree-with-clear-explanation
http://bookshadow.com/weblog/2015/11/18/leetcode-range-sum-query-mutable/