Leecode hot100 - 303. 区域和检索
题目描述
303. 区域和检索 - 数组不可变 - 力扣(LeetCode)
给定一个整数数组 nums
,处理以下类型的多个查询:
- 计算索引
left
和right
(包含left
和right
)之间的nums
元素的 和 ,其中left <= right
实现 NumArray
类:
NumArray(int[] nums)
使用数组nums
初始化对象int sumRange(int i, int j)
返回数组nums
中索引left
和right
之间的元素的 总和 ,包含left
和right
两点(也就是nums[left] + nums[left + 1] + ... + nums[right]
)
示例 1:
输入: ["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))
思路
- 定义一个前缀和数组
s
,其中s[0] = 0
,s[i]
表示原数组a
中前i
个元素的和 - 递推关系:
s[i] = s[i-1] + a[i-1]
(因为s[i]
是前i-1
个元素的和)
这样一来:
- 原数组中从下标
left
到right
(包含两端)的子数组和 - 就等于
s[right+1] - s[left]
举例:
原数组 a = [-2,0,3,-5,2,-1]
前缀和数组 s = [0, -2, -2, 1, -4, -2, -3]
计算子数组 [0,3,-5]
(下标 1 到 3)的和:
s[4] - s[1] = (-4) - (-2) = -2
,与实际计算 0+3+(-5) = -2
一致。
引入 s[0] = 0
是为了统一计算逻辑,比如计算从下标 0 开始的子数组和时,就可以直接用 s[right+1] - s[0]
。
代码
class NumArray:
def __init__(self, nums: List[int]):
s = [0] * (len(nums) + 1) # 定义s[0] = 0 前0个元素的和
for i, x in enumerate(nums):
s[i+1] = s[i] + x
self.s = s
def sumRange(self, left: int, right: int) -> int:
return self.s[right+1] - self.s[left]
# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# param_1 = obj.sumRange(left,right)