差分数组:
1109. 航班预订统计 https://leetcode-cn.com/problems/corporate-flight-bookings/
1094. 拼车 https://leetcode-cn.com/problems/car-pooling/
算法参考:
前缀和:
构造前缀和:
最好是前置一个0
int *preSum = (int *)malloc(sizeof(int) * (numsSize + 1));
preSum[0] = 0; // 前缀和做一个前置空内容
// 真正的前缀和是从preSum的1开始的
for (int i = 0;i < numsSize;++i) {
preSum[i + 1] = preSum[i] + nums[i];
}
如果要求任意区间内的元素的和,如 i~ j这个区间里面的元素的和:
// 上面这么写,就是为了下面循环可以算上nums[0]
int res = 0;
for (int left = 0;left < numsSize;++left) {
for (int right = left;right < numsSize;++right) {
// 区间和【left .. right】,注意下标
if (preSum[right + 1] - preSum[left] == k) {
res++;
}
}
}
计算区间和为k的所有情况
假设现在有数组a0、a1、a2、a3.....
S0 = 0;
S1 = a0;
S2 = a0 + a1;
S3 = a0 + a1 + a2;
S4 = ...........................;
一般需要配合Hash map一起使用:
前缀和介绍:
典型题目:
523. 连续的子数组和 https://leetcode-cn.com/problems/continuous-subarray-sum/
974. 和可被 K 整除的子数组 https://leetcode-cn.com/problems/subarray-sums-divisible-by-k/
560. 和为K的子数组 https://leetcode-cn.com/problems/subarray-sum-equals-k/
以560为例:
// hash map
typedef struct HashMap{
int preSum; // key 保存前缀和
int count; // 保存计数值
UT_hash_handle hh;
}HashMap;
int subarraySum(int* nums, int numsSize, int k){
if (nums == NULL) {
return 0;
}
// 几乎所有的前缀和使用UT Hash进行优化的时候,均需要使用到一个前置0的提前变量
HashMap *hashHandle = NULL;
HashMap *tmp = (HashMap *)malloc(sizeof(HashMap));
tmp->preSum = 0;
tmp->count = 1; //这部分必须是1
HASH_ADD_INT(hashHandle, preSum, tmp);
int pre = 0;
int res = 0;
for (int i = 0;i < numsSize;++i) {
pre += nums[i];
int value = pre - k; // 顺序不能反了,和很有可能是k或者k的倍数
HASH_FIND_INT(hashHandle, &value, tmp);
if (tmp != NULL) {
res += tmp->count;
}
//如果是相同的前缀和,那么需要更新计数值,UT Hash不允许存入preSum数值相同的内容
// HASH_FIND_INT(hashHandle, &pre, tmp);
/*
[1,2,3]
3
*/
if (tmp != NULL) {
tmp->count++; // 要自增
} else {
tmp = (HashMap *)malloc(sizeof(HashMap));
tmp->preSum = pre;
tmp->count = 1;
HASH_ADD_INT(hashHandle, preSum, tmp);
}
}
return res;
}