问题描述:https://leetcode.com/problems/range-sum-query-mutable/
问题分析:看到这道题心里一想这不和前几道题大同小异吗,然后就想怎么在前面的方法上改改。然后刷刷写了代码1,然后发现超时,然后查了查java有个SortedMap这个接口,喜出望外,刷刷改成了代码2,结果还是超时,于是再冥思苦想数小时,无果,遂查资料,方知原来有个树状数组的事物存在。
这个树状数组到底是什么鬼,请自行百度,按照树状数组的写法,写成了代码3,AC
代码1:
public class NumArray {
int[] nums;
HashMap<Integer,Integer> maps;
int[] processed;
boolean isUgly = false;
public NumArray(int[] nums) {
if(nums.length == 0){
isUgly = true;
return;
}
this.nums = nums;
maps = new HashMap<>();
processed = new int[nums.length];
processed[0] = nums[0];
for(int i = 1;i<nums.length;i++){
processed[i] = processed[i-1]+nums[i];
}
}
void update(int i, int val) {
int gap = nums[i] - val;
maps.put(i,gap);
}
public int sumRange(int i, int j) {
Set set = maps.entrySet();
Iterator iterator = set.iterator();
int sum = 0;
while(iterator.hasNext()){
Map.Entry entry = (Map.Entry)iterator.next();
int key = (int)entry.getKey();
int value = (int)entry.getValue();
if(key >= i && key <=j){
sum+=value;
}
}
return processed[j] - processed[i]+sum;
}
}
代码2:
//通过使用TreeMap数据结构来实现map的有序化,然后利用submap选出在某段的大小,但仍然超时
import java.util.SortedMap;
public class NumArray {
int[] nums;
SortedMap<Integer,Integer> maps;
int[] processed;
boolean isUgly = false;
public NumArray(int[] nums) {
if(nums.length == 0){
isUgly = true;
return;
}
this.nums = nums;
maps = new TreeMap<>();
processed = new int[nums.length];
processed[0] = nums[0];
for(int i = 1;i<nums.length;i++){
processed[i] = processed[i-1]+nums[i];
}
}
void update(int i, int val) {
int gap = nums[i] - val;
maps.put(i,gap);
}
public int sumRange(int i, int j) {
SortedMap<Integer,Integer> submap = maps.subMap(i,j+1);
int sum = 0;
Set set = submap.entrySet();
Iterator iterator = set.iterator();
while(iterator.hasNext()){
Map.Entry entry = (Map.Entry)iterator.next();
int value = (int)entry.getValue();
sum += value;
}
return processed[j] - processed[i]+sum;
}
}
代码3:
public class NumArray {
int[] processed;
int[] nums;
int length;
public NumArray(int[] nums) {
length = nums.length;
processed = new int[length+1];
this.nums = nums;
//init processed
for(int i = 1;i<=length;i++){
int sum = 0;
int count = 1;
int counter = lowBit(i);
while(count <= counter){
sum += nums[i-count];
count++;
}
processed[i] = sum;
}
}
void update(int i, int val) {
//更新树状数组
int gap = val - nums[i];
nums[i] = val;
int index = i+1;
while(index <= length){
processed[index] += gap;
index += lowBit(index);
}
}
public int sumRange(int i, int j) {
return sum(j+1) - sum(i);
}
private int sum(int index){
int sum = 0;
while(index > 0){
sum += processed[index];
index -= lowBit(index);
}
return sum;
}
private int lowBit(int index){
return index & (-index);
}
}