返回
LeetCode 303:区域和检索——数组不可变
前端
2023-10-25 18:39:06
问题
LeetCode 303:区域和检索——数组不可变 给定一个整数数组 nums ,求出数组从索引 i 到 j(i ≤ j)范围内元素的总和,包含 i、j 两点。
示例 1:
输入:nums = [-2, 0, 3, -5, 2, -1],i = 0,j = 2
输出:1
解释:求出nums[0] + nums[1] + nums[2] = (-2) + 0 + 3 = 1
示例 2:
输入:nums = [-2, 0, 3, -5, 2, -1],i = 2,j = 5
输出:-1
解释:求出nums[2] + nums[3] + nums[4] + nums[5] = 3 + (-5) + 2 + (-1) = -1
解题思路
暴力求解法
最直接的解法是暴力求解,每次查询时,直接累加从索引 i 到 j 之间的元素值。这种方法的时间复杂度为 O(n),其中 n 是数组 nums 的长度。
def range_sum(nums, i, j):
sum = 0
for k in range(i, j + 1):
sum += nums[k]
return sum
前缀和优化
为了优化暴力求解法的效率,我们可以使用前缀和优化技术。前缀和数组 preSum[i]存储着从索引 0 到 i 的元素和,因此,我们可以通过以下公式计算从索引 i 到 j 的元素和:
sum(i, j) = preSum[j] - preSum[i - 1]
前缀和数组可以一次性预处理得到,时间复杂度为 O(n),之后每次查询的时间复杂度仅为 O(1)。
def range_sum(nums):
n = len(nums)
preSum = [0] * (n + 1)
for i in range(n):
preSum[i + 1] = preSum[i] + nums[i]
def range_sum_helper(i, j):
return preSum[j + 1] - preSum[i]
return range_sum_helper
nums = [-2, 0, 3, -5, 2, -1]
range_sum = range_sum(nums)
print(range_sum(0, 2)) # 1
print(range_sum(2, 5)) # -1
动态规划
这个问题也可以使用动态规划来解决。我们定义状态 dp[i][j] 为从索引 i 到 j 的元素和。状态 dp[i][j] 可以由以下公式计算得到:
dp[i][j] = dp[i - 1][j] + nums[i]
边界条件是 dp[i][i] = nums[i]。
def range_sum(nums):
n = len(nums)
dp = [[0] * n for _ in range(n)]
for i in range(n):
dp[i][i] = nums[i]
for i in range(n - 1, -1, -1):
for j in range(i + 1, n):
dp[i][j] = dp[i - 1][j] + nums[i]
def range_sum_helper(i, j):
return dp[i][j]
return range_sum_helper
nums = [-2, 0, 3, -5, 2, -1]
range_sum = range_sum(nums)
print(range_sum(0, 2)) # 1
print(range_sum(2, 5)) # -1
总结
LeetCode 303:区域和检索——数组不可变 是一个经典的问题,有多种解法思路。暴力求解法的时间复杂度为 O(n),前缀和优化的时间复杂度为 O(1),动态规划的时间复杂度也为 O(1)。在实际应用中,我们可以根据具体情况选择合适的解法。