题目传送门:
Leetcode 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:
1. The array is only modifiable by the update function.
2. You may assume the number of calls to update and sumRange function is distributed evenly.
代码是这样给的:
public class NumArray {
public NumArray(int[] nums) {
}
public void update(int i, int val) {
}
public int sumRange(int i, int j) {
}
}
/**
* 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);
*/
思路
一开始用的方法(这个思路来自Range Sum Query - immutable):
- 构造函数中, 累加nums[i],使新的nums[i]表示原nums[0]加到nums[i].
- update函数,利用nums[i]-nums[i-1] (0特殊考虑)为原nums[i]的值,求出与更新值之间的diff差,依次修改大于等于i的nums值.
- sumRange,直接用nums[j]-nums[i-1] ,(i==0特殊考虑)
这个思路简单,但由于TLE(time limit exceed), 所以只好另找方法
题目描述中,有个tag,显示 Segment Tree. Binary Indexed Tree
顺藤摸瓜,我查了以下BIT(Segment Tree没咋看):
搞懂树状数组
树状数组详细讲解
还有一些细节我不是很理解, lowbit的延展性(确定哪些数据是有联系的).记忆吧.
思路1:一般方法
public class NumArray {
public int[] nums;
public NumArray(int[] nums) {
for(int i=1; i<nums.length;i++){
nums[i]+=nums[i-1];
}
this.nums = nums;
}
public void update(int i, int val) {
int diff;
if(i==0){
diff = nums[i]-val;
}
else{
diff = nums[i]-nums[i-1]-val;
}
for(int k=i;k<nums.length; k++){
nums[k]-=diff;
}
}
public int sumRange(int i, int j) {
if(i==0){
return nums[j];
}
else {
return nums[j]-nums[i-1];
}
}
}
思路2:BIT
public class NumArray {
public int[] BIT;
public int[] nums;
public int n;
public NumArray(int[] nums) {
n = nums.length+1;
BIT = new int[n];
for(int i=0; i<nums.length;i++){
init(i,nums[i]);
}
this.nums = nums;
}
public int lowbit(int k){
return k&(-k);
}
public void init(int i,int val){
i++;
while(i<n){
BIT[i] += val;
i += lowbit(i);
}
}
void update(int i, int val) {
int diff = val-nums[i];
nums[i]=val; // have to . should be careful
init(i,diff);
}
public int getSum(int i){
i++;
int sum=0;
while(i>0){
sum +=BIT[i];
i-=lowbit(i);
}
return sum;
}
public int sumRange(int i, int j) {
return getSum(j)-getSum(i-1);
}
}