560. 和为K的子数组
给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。
示例 1 :
1 | 输入:nums = [1,1,1], k = 2 |
说明 :
- 数组的长度为 [1, 20,000]。
- 数组中元素的范围是 [-1000, 1000] ,且整数 k 的范围是 [-1e7, 1e7]。
方法一:暴力
考虑以 i 结尾和为 k 的连续子数组个数,我们需要统计符合条件的下标 j 的个数,其中 0 <= j <= i
,且[j...i]
这个子数组的和恰好为 k。我们可以枚举 j 的值,然后再使用 O(n)的时间复杂度来求和,那样就达到O(n^3) 时间复杂度。如果我们知道[j, i]
子数组的和,就能在O(1)时间求出[j - 1, i]
子数组的和,因此我们初始时令 j = i,在循环中使 j 变小,同时维护一个数组和 sum。我们就能在O(1)时间内得到子数组[j...i]
的和。
1 | class Solution { |
时间复杂度O(n^2),空间复杂度O(1)。
方法二:前缀和+哈希表优化
我们定义 pre[i] 为 [0 … i] 内所有数的和,则有:
$$
pre[i] = pre[i - 1] + nums[i]
$$
那么 [j … i]子数组为 k ,这个条件可以转化为:
$$
pre[i] - pre[j - 1] == k
$$
简单移项得到:
$$
pre[j - 1] == pre[i] - k
$$
我们考虑 以 i 结尾的和为 k 的连续子数组时,只要统计有多少个前缀和为 pre[i] - k 的 pre[j] 即可。我们建立哈希表 map,使用和为键,出现的次数为相应的值,记录pre[i] 出现的次数,从左至右边更新 map,同时维护一个前缀和变量 pre,这样在计算 pre[i]时直接使用。
1 | class Solution { |
时间复杂度O(n),空间复杂度O(n)。