和相同的二元子数组

题型分类:
恰好型滑动窗口
一、恰好型滑动窗口思路
例如,要计算有多少个元素和恰好等于 k 的子数组,可以把问题变成:
1.计算有多少个元素和 ≥k 的子数组。
2.计算有多少个元素和 >k,也就是 ≥k+1 的子数组。
也就是说将恰好型滑动窗口转化为两个越长越合法型滑动窗口问题
二、越长越合法型滑动窗口解题思路?
由于本题 nums[i] 均为非负数,子数组越长,元素和越大,所以是「越长越合法」的计数滑窗问题。一般要写 ans += left。
1.1 为什么要写ans += left?
当内层循环条件为维护窗口的合法性时,内层循环结束后,[left,right] 这个子数组是不满足题目要求的,但在退出循环之前的最后一轮循环,[left−1,right] 是满足题目要求的。所以 [left−1,right],还有 [left−2,right],[left−3,right],…,[0,right] 都是满足要求的。也就是说,当右端点固定在 right 时,左端点在 0,1,2,…,left−1 的所有子数组都是满足要求的,这一共有 left 个。
1.2 代码思路
- 外层枚举右端点,while循环维护合法窗口,
- 当窗口合法时,进入内层循环,移动左端点,直到窗口再次不合法,
- 此时left形成的窗口是非法的,意味着左端点为0到left-1的窗口是合法,因此合法窗口个数为left-1-0+1 = left,
- 通过ans += left;把每个固定右端点的合法窗口个数累加,
- 得到合法窗口的总个数,返回ans。
java代码实现如下:
class Solution {
public int numSubarraysWithSum(int[] nums, int goal) {
//因此ans = left;
int ans = 0;
int sum1=0,sum2 = 0;
int left1=0,left2 = 0;
for(int i = 0;i<nums.length;i++){
sum1 += nums[i];
while(left1<=i && sum1 >= goal) {
sum1 -= nums[left1];
left1++;
}
ans += left1;
sum2 += nums[i];
while(sum2>goal){
sum2 -= nums[left2];
left2++;
}
ans -= left2;
}
return ans;
}
}

浙公网安备 33010602011771号