题目介绍
给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。
子数组是数组中元素的连续非空序列。
示例 1:
输入:nums = [1,1,1], k = 2
输出:2
示例 2:
输入:nums = [1,2,3], k = 3
输出:2
提示:
- 1 <= nums.length <= 2 * 104
- -1000 <= nums[i] <= 1000
- -107 <= k <= 107
分析
首先我在做题的时候忽视了“子数组”这个概念。
子数组
子数组是数组中元素的连续非空序列。
字符串的子串是字符串中元素的连续序列。可以为空串。
数组的子序列、字符串的子序列是可以不连续的。
求和
题目要求我们求和为k的子数组个数。
我们应该优先考虑使用遍历的方式来实现,由于子数组存在连续性,所以我们考虑设置两个指针,分别指向子数组的起始位置和结束位置。
尾指针从起始位置开始向后遍历,头指针从尾指针的位置向前遍历。
我们从尾指针所在位置开始计算子数组的和,当和等于k时,我们就找到了一个符合要求的子数组。
但是注意头指针的遍历必须从尾指针的位置开始,一致遍历到起始位置。
这是因为数组不是有序的,在遍历过程中我们可能遇到0,也可能遇到负数,造成在多个位置都能产生和为k的情况。
实现
代码
1 | class Solution { |
时空复杂度分析
时间复杂度有O(n^2),空间复杂度有O(1)。
优化
考虑到对于每一个 i,我们都需要从 i 开始向起始位置遍历,这会导致重复计算。
我们可以考虑使用前缀和的方式来优化。
前缀和是指数组中前 i 个元素的和。
我们可以用一个数组来存储前缀和,然后在遍历过程中,用当前位置的前缀和减去之前的前缀和,就可以得到子数组的和。
如果这个和等于k,那么我们就找到了一个符合要求的子数组。
我们可以用一个哈希表来存储前缀和出现的次数,然后在遍历过程中,用当前位置的前缀和减去k,就可以得到之前出现过的前缀和。
如果之前出现过这个前缀和,那么我们就可以用当前位置的前缀和减去之前出现过的前缀和,就可以得到一个符合要求的子数组。
我们可以用一个变量来记录符合要求的子数组的个数。
优化代码
1 | class Solution { |
时空复杂度分析
时间复杂度有O(n),空间复杂度有O(n)。