🚩传送门:牛客题目
力扣题目

题目

给定一个整数数组和一个整数 [NC]125. 和为 K 的连续子数组 - 图1 ,请找到该数组中和为 [NC]125. 和为 K 的连续子数组 - 图2 的连续子数组的个数。

示例 1 :

输入:nums = [1,1,1], k = 2 输出: 2 解释: 此题 [1,1] 与 [1,1] 为两种不同的情况

示例 2 :

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

牛客求该数组中和为 [NC]125. 和为 K 的连续子数组 - 图3 的连续子数组的最大长度。
力扣求该数组中和为 [NC]125. 和为 K 的连续子数组 - 图4 的连续子数组的个数

力扣思路:前缀和 + 哈希表优化

👉 定义:[NC]125. 和为 K 的连续子数组 - 图5[NC]125. 和为 K 的连续子数组 - 图6 里所有数的和,则 [NC]125. 和为 K 的连续子数组 - 图7 可以由 [NC]125. 和为 K 的连续子数组 - 图8 递推而来

[NC]125. 和为 K 的连续子数组 - 图9

那么[NC]125. 和为 K 的连续子数组 - 图10 这个子数组和为 [NC]125. 和为 K 的连续子数组 - 图11这个条件我们可以转化为

[NC]125. 和为 K 的连续子数组 - 图12

对于每个 [NC]125. 和为 K 的连续子数组 - 图13 我们需要从[NC]125. 和为 K 的连续子数组 - 图14 中遍历,速度太慢,优化一下[NC]125. 和为 K 的连续子数组 - 图15 存入 Hashmap

  • [NC]125. 和为 K 的连续子数组 - 图16 :为[NC]125. 和为 K 的连续子数组 - 图17的值,即 [NC]125. 和为 K 的连续子数组 - 图18 里所有数的前缀和
  • [NC]125. 和为 K 的连续子数组 - 图19 :为[NC]125. 和为 K 的连续子数组 - 图20个数,即 [NC]125. 和为 K 的连续子数组 - 图21 里所有数的和为[NC]125. 和为 K 的连续子数组 - 图22的序列个数

    例如:[0,1] 、[0 ,1,2,-3] 前缀和都是 0 ,0 是做 key,2个序列数做 value

那么[NC]125. 和为 K 的连续子数组 - 图23 这个子数组和为 [NC]125. 和为 K 的连续子数组 - 图24这个条件我们可以转化为

[NC]125. 和为 K 的连续子数组 - 图25

我们只需要知道[NC]125. 和为 K 的连续子数组 - 图26 中有多少个和为 [NC]125. 和为 K 的连续子数组 - 图27[NC]125. 和为 K 的连续子数组 - 图28 就可以了
image.png

复杂度分析

时间复杂度: [NC]125. 和为 K 的连续子数组 - 图30 ,其中 [NC]125. 和为 K 的连续子数组 - 图31 是数组的长度,只需要遍历数组一次。中间利用哈希表查询删除的复杂度均为[NC]125. 和为 K 的连续子数组 - 图32

空间复杂度:[NC]125. 和为 K 的连续子数组 - 图33 ,即为存储 [NC]125. 和为 K 的连续子数组 - 图34 所有状态使用的空间,哈希表在最坏情况下可能有 [NC]125. 和为 K 的连续子数组 - 图35 个不同的键值

我的代码

  1. public class Solution {
  2. public int subarraySum(int[] nums, int k) {
  3. int res = 0;
  4. int sum = 0;
  5. HashMap < Integer, Integer > mp = new HashMap < > ();
  6. mp.put(0, 1);
  7. for (int i = 0; i < nums.length; i++) {
  8. sum += nums[i];
  9. if (mp.containsKey(sum - k)) {
  10. res += mp.get(sum - k);
  11. }
  12. mp.put(sum, mp.getOrDefault(sum, 0) + 1);
  13. }
  14. return res;
  15. }
  16. }

题目

给定一个整数数组和一个整数 [NC]125. 和为 K 的连续子数组 - 图36 ,请找到该数组中和为 [NC]125. 和为 K 的连续子数组 - 图37 的连续子数组的最大长度

示例 1 :

输入:nums = [1,1,1], k = 2 输出: 2 解释: 此题 [1,1] 长度为 2

示例 2 :

输入:nums = [1,2,3], k = 3 输出: 2 解释: 此题 [1,2] 长度为 2

力扣思路:前缀和 + 哈希表优化

[NC]125. 和为 K 的连续子数组 - 图38 存入 Hashmap

  • [NC]125. 和为 K 的连续子数组 - 图39 :为[NC]125. 和为 K 的连续子数组 - 图40的值,即 [NC]125. 和为 K 的连续子数组 - 图41 里所有数的前缀和
  • [NC]125. 和为 K 的连续子数组 - 图42 :为[NC]125. 和为 K 的连续子数组 - 图43最小的下标,贪心思想:相同的 [NC]125. 和为 K 的连续子数组 - 图44,想让长度尽量的厂,其[NC]125. 和为 K 的连续子数组 - 图45要尽量的小。

    public class Solution {
    
      public int maxlenEqualK (int[] arr, int k) {
          int res = 0;
          int sum = 0;
          HashMap < Integer, Integer > mp = new HashMap <> ();
          mp.put(0, -1);
          for (int i = 0; i < arr.length; i++) {
              sum += arr[i];
              if (mp.containsKey(sum - k)) {
                  // 查看能否刷新答案
                  res =Math.max(res,i-mp.get(sum - k));
              }
              // 如果已经存在就使用默认的,否则插入当前的i
              mp.put(sum, mp.getOrDefault(sum, i));
          }
          return res;
      }
    }