和相同的二元子数组

image

题型分类:
恰好型滑动窗口

一、恰好型滑动窗口思路
例如,要计算有多少个元素和恰好等于 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;
    }
}
posted @ 2026-08-18 12:49  ZealousMclaren  阅读(3)  评论(0)    收藏  举报