303.区域和检索-数组不可变
方法:前缀和
存储数组nums的值,每次调用sumRange时,通过循环的方法计算数组nums从下标i到下标j范围内的元素和,需要计算j-i+1个元素的和,由于每次检索的时间和检索的下标范围有关,因此检索的时间复杂度较高,如果检索次数较多,则会超出时间限制。
由于会进行多次检索,即每次调用sumRange,因此为了降低检索的总时间,应该降低sumRange的时间复杂度,最理想的情况是时间复杂度O(1),为了将检索的时间复杂度降到O(1),需要在初始化的时候进行预处理。
由此可知,要计算sumRange(i,j),则需要计算数组nums在下标j和下标i-1的前缀和,然后计算两个前缀和的差。
如果可以在初始化的时候计算出数组nums在每个下标处的前缀和,即可满足每次调用sumRange的时间复杂度都是O(1)
具体实现:
假设数组nums的长度为n,创建长度为n+1的前缀和和数组nums,对于0≤i<n都有sums[i+1]=sums[i]+nums[i],则当0<i≤n时,sums[i]表示数组nums从下标0到下标i-1的前缀和
将前缀和数组sums的长度设为n+1的目的是为了方便计算sumRange(i,j),不需要对i=0的情况特殊处理,此时有:
sumRange(i,j)=sums[j+1]-sums[i]
class NumArray {
int[] sums;
public NumArray(int[] nums) {
int n = nums.length;
sums = new int[n+1];
for(int i = 0;i < n; i++){
sums[i + 1] = sums[i] + nums[i];
}
}
public int sumRange(int left, int right) {
return sums[right + 1] - sums[left];
}
}
/**
* Your NumArray object will be instantiated and called as such:
* NumArray obj = new NumArray(nums);
* int param_1 = obj.sumRange(left,right);
*/