10.和为K的子数组

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。

子数组是数组中元素的连续非空序列。

示例 1:

输入:nums = [1,1,1], k = 2
输出:2

示例 2:

输入:nums = [1,2,3], k = 3
输出:2

提示:

  • 1 <= nums.length <= 2 * 104
  • -1000 <= nums[i] <= 1000
  • -107 <= k <= 107

思路:
由于子数组表示的数组中元素的连续非空序列,所以题目意思就是让我们找一个区间使得区间和为k,由此我们可以联想到前缀和,pre[i]表示数组前i个元素的和,则pre[j]-pre[i]即为第i+1个元素到第j个元素的和,即区间[i+1,j]的元素和,容易想到可以遍历左右端点来确定区间,利用前缀和判断区间和是否满足条件,时间复杂度为n2

class Solution {
    public int subarraySum(int[] nums, int k) {
        int res = 0;
        int len = nums.length;
        int[] temp = new int[100005];
        for(int i = 1;i<=len;i++){
            temp[i] = temp[i-1]+nums[i-1];
        }
        for(int i = 1;i <= len;i++){
            for(int j = i;j <= len;j++){
                if(temp[j]-temp[i-1]==k)res++;
            }
        }
        return res;
    }
}

考虑优化:
假设区间[i+1,j]的数组和等于k,即pre[j]-pre[i]==k,那是不是说明pre[i]=pre[j]-k,由于i比j小,故pre[i]肯定比pre[j]先计算,我们只需要遍历一个变量j,并判断pre[j]-k是否已经存在,存在的次数即为满足条件的区间个数,遍历过程中需要不断记录pre[j]出现次数,即将pre[j]记录在hashMap中

class Solution {
    public int subarraySum(int[] nums, int k) {
        int res = 0,pre = 0;
        Map<Integer,Integer>mp = new HashMap<>();
        mp.put(0, 1);
        for(int i = 0;i < nums.length;i++){
            pre += nums[i];
            if(mp.containsKey(pre-k))res+=mp.get(pre-k);
            mp.put(pre,mp.getOrDefault(pre,0)+1);
        }
        return res;
    }
}
posted @ 2025-04-10 09:45  回忆、少年  阅读(23)  评论(0)    收藏  举报