题目:
Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.
Example:
Given nums = [-2, 0, 3, -5, 2, -1]
sumRange(0, 2) -> 1
sumRange(2, 5) -> -1
sumRange(0, 5) -> -3
Note:
You may assume that the array does not change.
There are many calls to sumRange function.
解析:
这一题是求指定区间数组元素的和。并且要求不能改变原数组。这个方法会经常被调用。
由于经常被调用,如果按常规方法,开销会比较大,每次都要遍历并求和。已知数组不会改变,我们可以考虑能不能先计算一部分,节约后面调用的开销。
重新定义一个数组,这个数组保存从第一个元素到当前元素的累计值。现在想想,再求一个区间,只需要求两个值的差即可。
原数组:[1,2,1,9,5]
保存的数组:[0,1,3,4,13,18]
sumRange(2,4) = 18 - 3 = 15
Q:为什么第一个元素要置0?
有时候在思考一个问题时,可以反着思考,比如:如果不置0会怎么样?
那么就需要判断边界条件,首先是代码不够清晰,分支多;其次,性能也有影响。而加一个0可以将问题表现统一。 这里有兴趣的可以去看看linus 用双重指针操作链表的例子。链接
我觉得这题体现出把计算提前的思想,比如模板元编程,可以在编译期间计算出结果,而不用在运行时计算,运行次数越多,越体现优势。
答案:
class NumArray {
private:
vector<int> sumArray = {0};
public:
NumArray(vector<int> nums) {
int sum = 0;
for (int n : nums) {
sum += n;
sumArray.push_back(sum);
}
}
int sumRange(int i, int j) {
return sumArray[j + 1] - sumArray[i];
}
};
/**
* Your NumArray object will be instantiated and called as such:
* NumArray obj = new NumArray(nums);
* int param_1 = obj.sumRange(i,j);
*/