303. 区域和检索 - 数组不可变 - 力扣(LeetCode)
动态规划~
前缀和
最朴素的思想是存储数组nums的值,每次调用sumRange时,通过循环的方法计算数组nums从下标i到下标j的元素和,需要计算j-i+1个元素的和。由于每次检索的时间和检索的下标范围有关,因此检索的时间复杂度较高,如果检索的次数过多,会超出时间限制。
我们应该尽量降低sumRange的时间复杂度,最理想的时间复杂度是O(1)。
因此,要计算sumRange(i,j),则需要计算数组nums在下标i-1和j的前缀和,并计算两个前缀和的差。如果可以在初始化时就计算nums在每个下标的前缀和。即可满足调用sumRange的时间复杂度都是O(1)。
具体实现方面,假设数组的长度nums等于n,创建长度为n+1的前缀和数组nums,sums[i+1]=sums[i]+nums[i],则sums[i]表示数组从0到下标i-1的前缀和。
将前缀和数组 sum 的长度设为 n+1的目的是为了方便计算 sumRange(i,j),不需要对 i=0的情况特殊处理。此时有:
typedef struct {
int* sums;
} NumArray;
NumArray* numArrayCreate(int* nums, int numsSize) {
NumArray* ret=malloc(sizeof(NumArray));
ret->sums=malloc(sizeof(int)*(numsSize+1));
ret->sums[0]=0;
for(int i=0;i<numsSize;i++)
{
ret->sums[i+1]=ret->sums[i]+nums[i];
}
return ret;
}
int numArraySumRange(NumArray* obj, int i, int j) {
return obj->sums[j+1]-obj->sums[i];
}
void numArrayFree(NumArray* obj) {
free(obj->sums);
}
/**
* Your NumArray struct will be instantiated and called as such:
* NumArray* obj = numArrayCreate(nums, numsSize);
* int param_1 = numArraySumRange(obj, left, right);
* numArrayFree(obj);
*/