1. 题目信息
- 题号.题目名称:303.区域和检索 - 数组不可变
- 题目叙述:给定一个整数数组
nums
,处理以下类型的多个查询:- 计算索引
left
和right
(包含left
和right
)之间的nums
元素的 和 ,其中left <= right
实现NumArray
类:
NumArray(int[] nums)
使用数组nums
初始化对象int sumRange(int left, int right)
返回数组nums
中索引left
和right
之间的元素的 总和 ,包含left
和right
两点(也就是nums[left] + nums[left + 1] + ... + nums[right]
)
- 计算索引
2. 模式识别
本题属于前缀和问题。当需要多次查询数组中某个区间的和时,如果每次都直接遍历区间求和,时间复杂度较高。而使用前缀和可以预先计算好数组的前缀和数组,后续每次查询的时间复杂度可以降为 O ( 1 ) O(1) O(1)。
3. 考点分析
本题主要考查前缀和数组的构建和使用。通过构建前缀和数组,将区间和的查询时间复杂度从 O ( n ) O(n) O(n) 降低到 O ( 1 ) O(1) O(1),需要理解前缀和数组的原理和应用场景。
4. 所有解法
- 暴力解法:每次调用
sumRange
函数时,直接遍历left
到right
区间,累加元素求和。时间复杂度为 O ( n ) O(n) O(n),其中 n n n 是区间的长度。空间复杂度为 O ( 1 ) O(1) O(1)。 - 前缀和解法:预先计算一个前缀和数组
prefixSum
,其中prefixSum[i]
表示数组nums
中前i
个元素的和。对于查询sumRange(left, right)
,可以通过prefixSum[right + 1] - prefixSum[left]
得到结果。时间复杂度为 O ( 1 ) O(1) O(1),空间复杂度为 O ( n ) O(n) O(n)。
5. 最优解法(前缀和解法)的C语言代码
#include <stdlib.h>
// 定义 NumArray 结构体
typedef struct {
int* prefixSum; // 前缀和数组
int size; // 数组的大小
} NumArray;
// 初始化 NumArray 对象
NumArray* numArrayCreate(int* nums, int numsSize) {
// 为 NumArray 对象分配内存
NumArray* obj = (NumArray*)malloc(sizeof(NumArray));
// 为前缀和数组分配内存
obj->prefixSum = (int*)malloc((numsSize + 1) * sizeof(int));
// 记录数组的大小
obj->size = numsSize;
// 前缀和数组的第一个元素为 0
obj->prefixSum[0] = 0;
// 计算前缀和数组
for (int i = 0; i < numsSize; i++) {
obj->prefixSum[i + 1] = obj->prefixSum[i] + nums[i];
}
return obj;
}
// 计算指定区间的和
int numArraySumRange(NumArray* obj, int left, int right) {
// 根据前缀和数组计算区间和
return obj->prefixSum[right + 1] - obj->prefixSum[left];
}
// 释放 NumArray 对象占用的内存
void numArrayFree(NumArray* obj) {