LeetCode.560-和为k的子数组

110 阅读2分钟

解题随记

给你一个整数数组 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为空

思路

因为需要连续,那就有两种连续的方式,一种是从下标0开始,也就是从头开始,这种好解决,从头遍历累加就可以了;还有一种不是从下标0开始,也就是中间部分,这种我们就要使用前缀和的方式来解决了。

前缀和举例: 数组:[3,4,7,2,-3,1,4,2] k:7

  • 第一种情况的比如:[3,4]
  • 第二种情况的比如:[7,2,-3,1]

第二种可以看做:[3,4,7,2,-3,1] - [3,4] = [7,2,-3,1],即我们用f(x) 表示从0开始到x这个数的和(包含x),那公式就变成了f(x) - f(y) = f(y~x)。起始第一种也可以看做是该公式的一种变种。

那答案也就呼之欲出了,我们只需要统计所有从0开始的前缀和,并且计算其与k的差值,就可以知道有多少种可能了

附代码:

public static int subarraySum(int[] nums, int k){
    // 前缀和对象,key为前缀和的值,value为出现的次数
    Map<Integer, Integer> map = new HashMap<>();
    map.put(0, 1);
    // 求和
    int sum = 0;
    // 结果集
    int count = 0;
    for (int num : nums) {
        sum += num;
        // 判断是否之前出现了与k的差相同的数,比如上面例子中的当此时num下标为5(值为1)的时候,sum此时为14,我们仅需要判断14-k(7)= 7的数是否出现过,出现则统计count次数就可以
        if (map.get(sum - k) != null) {
            // 这里直接加次数而不是加1是因为,我们可以知道每次出现必定下标不一样,且结尾数字的下标也不一样,所以故应该加上所有
            int i1 = map.get(sum - k);
            count+= i1;
        }
        // 放入map中,如果已经出现则次数加1,代表起点的不同
        map.put(sum, map.getOrDefault(sum, 0) + 1);
    }
    return count;
}

如果有不对的地方希望大家斧正哈!