930 和相同的二元子数组-中等
题目:
给你一个二元数组 nums
,和一个整数 goal
,请你统计并返回有多少个和为 goal
的 非空 子数组。
子数组 是数组的一段连续部分。
分析:
整体思路是求数组的前缀和,假设有两个坐标 i 和 j,且 i < j。
前 i 个元素的和为 sum_i,前 j 个元素的和为 sum_j,如果 sum_j - sum_i = goal;
那么区间[i, j] 就是一种解。
考虑到数组中只有 0 和 1,那么当元素为 0 的时候,前缀和的大小不变,但前缀和的个数增加了。这个个数是要计算到总结果中的,因为不包含该元素 0 和包含该元素 0 都是非空子数组。
假设,sum_i 等于 3 出现了4次,sum_j 等于 5 出现了 3 次,在 goal 为 2 的情况下。
sum_j 等于 5 连续出现 3 次,对最终的结果增加了 4+4+4, 总共 12 次。【这是11-13行代码】
// date 2023/11/21
func numSubarraysWithSum(nums []int, goal int) int {
var ans int
// 因为后面判断使用的时候是 sum-goal, 所以 sum 初始化为 0
sum := 0
cnt := make(map[int]int, 16) // 记录 前缀和 出现的次数
for _, v := range nums {
cnt[sum]++ // 前缀和 次数递增
sum += v // 前缀求和
// 每次都要计算
// 如果存在,表示 当前元素 和 之前的前缀和 能够构成一个解,
// 之前的前缀和 出现过几次,就是几个不同的非空子数组
if ct, ok := cnt[sum-goal]; ok {
ans += ct
}
}
return ans
}
最后更新于