力扣 930. 和相同的二元子数组

题目说明

  • 给你一个二元数组 nums ,和一个整数 goal ,请你统计并返回有多少个和为 goal非空 子数组。

    子数组 是数组的一段连续部分。

示例

示例 1:

1
2
3
4
5
6
7
8
输入:nums = [1,0,1,0,1], goal = 2
输出:4
解释:
如下面黑体所示,有 4 个满足题目要求的子数组:
[1,0,1,0,1]
[1,0,1,0,1]
[1,0,1,0,1]
[1,0,1,0,1]

示例 2:

1
2
输入:nums = [0,0,0,0,0], goal = 0
输出:15

笔者理解

此题是一道数组算法问题,在力扣题库中被定义为中等题。

解法

当笔者阅读完此题后,**笔者借鉴自宫水三叶大佬的解法**,让我们来看看具体如何实现的吧。

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
/*
* 前缀和+哈希
*/
public int numSubarraysWithSum(int[] nums, int goal) {
int n = nums.length;
// 前缀和数组
int[] sum = new int[n + 1];

for (int i = 1; i <= n; i++) {
sum[i] = sum[i - 1] + nums[i - 1];
}

Map<Integer, Integer> map = new HashMap<>();
map.put(0, 1);
int result = 0;

for (int i = 0; i < n; i++) {
// 当前遍历到的n + 1个数的和,作为右边界
int right = sum[i + 1];
// 左边界就是右边界减去目标值
int left = right - goal;
// 查看哈希表中之前有没有存过对应的前缀和,有就累加
// 至此,计算了一次当前位置前的区间了
result += map.getOrDefault(left, 0);
// 存储当前前缀和,方便之后计算区间和
map.put(right, map.getOrDefault(right, 0) + 1);
}

return result;
}
}

时间效率一般,空间效率都还行,可见此解法还比较适合此题;

image.png

总结

本题是今天的每日一题,难度是为中等,感兴趣的朋友都可以去尝试一下,此题还有其他更多的解法,朋友们可以自己逐一尝试。