开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情
和相同的二元子数组
给你一个二元数组 nums ,和一个整数 goal ,请你统计并返回有多少个和为 goal 的 非空 子数组。
子数组 是数组的一段连续部分。
示例1:
输入:nums = [1,0,1,0,1], goal = 2
输出:4
解释:
有 4 个满足题目要求的子数组:[1,0,1]、[1,0,1,0]、[0,1,0,1]、[1,0,1]
示例2:
输入: nums = [0,0,0,0,0], goal = 0
输出: 15
提示:
1 <= nums.length <= 3 * 104nums[i]不是0就是10 <= goal <= nums.length
解题思路:
- 使用滑动窗口找出符合条件的最大窗口 -- 固定 l,移动 r,当 sum > S 的时候再移动 l ,最后得到在当前 r 固定下符合条件的最大窗口 [l,r]
- 从 l 中分出一个临时指针 tempL,向右收缩找出所有[l,r] 中符合条件的子窗口
- r 指针继续移动,寻找下一个相对最大的窗口 [l,r]
我的答案:
/**
* @分析
* 1. 构建一个滑窗,然后满足和为 S
* 2. 滑窗向右扩展,只有当值大于 S,开始收缩 left,得到一个最大的符合条件的窗口
* 3. 当符合条件的时候 [l,r] 中最少已经有一个状态是符合的了,现在固定 r 指针,从 l 中另外分出一个指针,来循环判定
* 4. 之所以不直接用 l 收缩,是为了保证在 [l, r] 要保证最多,l一旦移动了,后面 r 继续移动的时候, l 就无法会到原来的位置,就会漏掉一些情况了
*/
var numSubarraysWithSum = function (A, S) {
let len = A.length
let res = 0
let sum = 0
let l = r = 0
while (r < len) {
sum += A[r]
// 只有当 sum > S 的时候,才会收缩 l 指针
while (sum > S) {
sum -= A[l]
l++
}
// 当条件符合的时候 -- 这里是重点
if (sum === S) {
let tempL = l,tempSum = sum
while(tempL<=r){
if(tempSum === S) res++
tempSum-=A[tempL]
tempL++
}
}
r++
}
return res
};
最后
如果有更好的解法或者思路, 欢迎在评论区和我交流~ ღ( ´・ᴗ・` )