題目:
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.
解析:
這一題是求指定區(qū)間數(shù)組元素的和。并且要求不能改變原數(shù)組。這個方法會經(jīng)常被調(diào)用。
由于經(jīng)常被調(diào)用,如果按常規(guī)方法,開銷會比較大,每次都要遍歷并求和。已知數(shù)組不會改變,我們可以考慮能不能先計算一部分,節(jié)約后面調(diào)用的開銷。
重新定義一個數(shù)組,這個數(shù)組保存從第一個元素到當(dāng)前元素的累計值。現(xiàn)在想想,再求一個區(qū)間,只需要求兩個值的差即可。
原數(shù)組:[1,2,1,9,5]
保存的數(shù)組:[0,1,3,4,13,18]
sumRange(2,4) = 18 - 3 = 15
Q:為什么第一個元素要置0?
有時候在思考一個問題時,可以反著思考,比如:如果不置0會怎么樣?
那么就需要判斷邊界條件,首先是代碼不夠清晰,分支多;其次,性能也有影響。而加一個0可以將問題表現(xiàn)統(tǒng)一。 這里有興趣的可以去看看linus 用雙重指針操作鏈表的例子。鏈接
我覺得這題體現(xiàn)出把計算提前的思想,比如模板元編程,可以在編譯期間計算出結(jié)果,而不用在運行時計算,運行次數(shù)越多,越體現(xiàn)優(yōu)勢。
答案:
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);
*/