LeetCode 303 区域检索 - 数组不可变
1.题目描述:
给定一个整数数组 nums
,求出数组从索引 i
到 j
(i ≤ j
)范围内元素的总和,包含 i
、j
两点。
示例:
输入:
[“NumArray”, “sumRange”, “sumRange”, “sumRange”]
[[[-2, 0, 3, -5, 2, -1]], [0, 2], [2, 5], [0, 5]]
输出:
[null, 1, -1, -3]
解释:
NumArray numArray = new NumArray([-2, 0, 3, -5, 2, -1]);
numArray.sumRange(0, 2); // return 1 ((-2) + 0 + 3)
numArray.sumRange(2, 5); // return -1 (3 + (-5) + 2 + (-1))
numArray.sumRange(0, 5); // return -3 ((-2) + 0 + 3 + (-5) + 2 + (-1))
2.题解:
-
对于一维数组,可以用前缀和来解决此类问题。
-
先建立一个与数组nums长度相等的数组sums,表示nums位置之前所有数字的和,并利用状态转移方程sums[i+1] = sums[i] + nums[i]
-
如果需要求 i,j 之间的数字之和, 只需要计算 sums[j+1] - sums[i]
时间复杂度:初始化需要遍历数组 nums 计算前缀和,时间复杂度是 O(n)
空间复杂度:O(n),其中 n 是数组 nums 的长度。需要创建一个长度为n+1 的前缀和数组。
c++:
class NumArray {
public:
//前缀和 满足: sum = s[j] - s[i-1]
vector<int> s ;
NumArray(vector<int>& nums) {
s.resize(nums.size()+ 1) ;
//前缀和第一个index 设为 1
for (int i = 0; i < nums.size(); i++) s[i+1] = s[i] + nums[i] ;
}
int sumRange(int left, int right) {
return s[right+1] - s[left] ;
}
};
/**
* Your NumArray object will be instantiated and called as such:
* NumArray* obj = new NumArray(nums);
* int param_1 = obj->sumRange(left,right);
*/
Golang:
type NumArray struct {
sums []int
}
func Constructor(nums []int) NumArray {
sums := make([]int, len(nums)+1)
for i, v := range nums {
sums[i+1] = sums[i] + v
}
return NumArray{sums}
}
func (this *NumArray) SumRange(left int, right int) int {
return this.sums[right+1] - this.sums[left]
}