在问 · 算法题解

303. 区域和检索 - 数组不可变

题目描述

输入一个整数数组 nums,之后会有很多次查询。每次查询给出两个下标 left 和 right(left <= right,下标从 0 开始),要求算出这一段元素的和。

实现 NumArray 类。构造函数接收数组 nums 并完成预处理。方法 sumRange(left, right) 返回从 nums[left] 一直加到 nums[right] 的结果,两端都计入。

数组在初始化后不会被修改。输入由方法名数组和参数数组组成,输出按顺序给出每次调用的返回值,构造调用记为 null。

示例 1
输入:操作 = ["NumArray","sumRange","sumRange","sumRange"]
参数 = [[[-2,0,3,-5,2,-1]],[0,2],[2,5],[0,5]]
输出:[null,1,-1,-3]

解释:三次查询分别是 (-2) + 0 + 3 = 1、3 + (-5) + 2 + (-1) = -1、全部元素之和 -3。

数据范围

  • 1 <= nums.length <= 10^4
  • -10^5 <= nums[i] <= 10^5
  • 0 <= left <= right < nums.length
  • sumRange 最多调用 10^4 次。

解题思路

构造时预处理前缀和 pre,pre[i] 是前 i 个元素的和(pre[0] = 0)。区间 [left, right] 的和就是 pre[right+1] - pre[left],每次查询只做一次减法。

为什么正确

pre[i] = nums[0] + nums[1] + ... + nums[i-1]。

复杂度分析

构造 O(n),每次查询 O(1);空间 O(n)。

易错点

前缀和数组比 nums 长 1,右端用 pre[right+1];写成 pre[right] - pre[left] 会漏掉 nums[right]。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class NumArray:
    def __init__(self, nums: List[int]):
        self.pre = [0]
        for x in nums:
            self.pre.append(self.pre[-1] + x)

    def sumRange(self, left: int, right: int) -> int:
        return self.pre[right + 1] - self.pre[left]

载入编辑器,自己跑一遍 →

设计 专题的其他题目

查看 设计 全部题目 →