一开始看到连续子数组就考虑用滑动窗口,滑动窗口模板如下
# 滑动窗口模板
left,right = 0, (0 or 1)
ret = total = 0
while right < len(nums):
更新total值
while 窗口内数据不满足要求
1. 更新total值
2. 收缩左边界
更新ret最大值
返回 ret
代码
int subarraySum(int* nums, int numsSize, int k){
int res = 0;
int sum = 0;
int left = 0;
int right = 0;
/* 滑动窗口 */
while (right < numsSize) {
sum += nums[right];
while (left < right && sum > k) {
sum -= nums[left];
left++;
}
if (sum == k) {
res++;
}
right++;
}
return res;
}
但是注意到数组中有负数,滑动窗口的原则是right增加后和变大,left增加后和变小,所以该题不适合用滑动窗口。
采用前缀和的思想
朴素前缀和
定义 preSum[i] 为 [0…i] 里所有数的和
preSum[i] = preSum[i-1] + nums[i]
j…i子数组和为k转换为 preSum[i]-preSum[j-1] == k
preSum[j-1] == preSum[i]-k;(j<i) 满足这个条件的就应该是子数组和为k
preSum[]数组遍历一遍就可以得到
求以 序号 i 结尾的和为 k 的连续子数组个数
只要统计有多少个前缀和为 preSum[i]−k 的 preSum[m] 即可。m<i
int subarraySum(int* nums, int numsSize, int k){
int res = 0;
int *perHeadSum = (int*)malloc(sizeof(int) * (numsSize + 1));
memset(perHeadSum, 0, sizeof(int) * (numsSize + 1));
for (int i = 0; i < numsSize; ++i) {
perHeadSum[i+1] = perHeadSum[i] + nums[i];
}
for (int i = 0; i < numsSize + 1; ++i) {
for (int j = i + 1; j < numsSize + 1; ++j) {
if (perHeadSum[j] - perHeadSum[i] == k) {
res++;
}
}
}
return res;
}
朴素前缀和中还有双重循环,如果数据太多肯定超时
前缀和+Hash
用哈希标保存该前缀和是否出现过,即可优化二重循环
typedef struct {
int sum;
int count;
UT_hash_handle hh;
} HashTable;
int subarraySum(int* nums, int numsSize, int k){
int res = 0;
int *perHeadSum = (int*)malloc(sizeof(int) * (numsSize + 1));
memset(perHeadSum, 0, sizeof(int) * (numsSize + 1));
HashTable *ht = NULL;
HashTable *sumTemp = (HashTable*)malloc(sizeof(HashTable));
sumTemp->sum = 0;
sumTemp->count = 1;
HASH_ADD_INT(ht, sum, sumTemp);
for (int i = 0; i < numsSize; ++i) {
perHeadSum[i+1] = perHeadSum[i] + nums[i];
HashTable *temp = NULL;
int findItem = perHeadSum[i+1] - k;
HASH_FIND_INT(ht, &findItem, temp);
if (temp != NULL) {
res += temp->count;
}
HashTable *perHeadSumItem = NULL;
int addKey = perHeadSum[i+1];
HASH_FIND_INT(ht, &addKey, perHeadSumItem);
if (perHeadSumItem == NULL) {
HashTable *perNum = (HashTable*)malloc(sizeof(HashTable));
perNum->sum = addKey;
perNum->count = 1;
HASH_ADD_INT(ht, sum, perNum);
} else {
perHeadSumItem->count++;
}
}
return res;
}
C语言用HASH太难了。。。