算法题-16

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

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

示例 1:

输入:nums = 1,1,1, k = 2

输出:2

示例 2:

输入:nums = 1,2,3, k = 3

输出:2

对于这道题如果我们一个一个试,我们也会试出来答案是2

复制代码
[1]        = 1 ❌
[1,1]      = 2 ✅
[1,1,1]    = 3 ❌
   [1]     = 1 ❌
   [1,1]   = 2 ✅
      [1]  = 1 ❌

但是我们在试的是够的一个关键问题是从某个位置j到i的连续和,numsj + ... + numsi

假如我们一直往右边加,我们会发现nums = 1,1,1,这个就是前缀和

位置 当前累计和
开始 0
0 1
1 2
2 3

看这个表,如果我们想知道有没有一段子数组和=2,我们发下,当我们在2位置的时候,前面有一个时刻的和是1,那么3-1=2,说明中间的那段=2,这样我们就找到了一个子数组

时间线:

0 ---- 1 ---- 2 ---- 3

↑ ↑

旧位置 现在

所以整体唯一的思想就是,不断地询问以前有没有一个"旧的累计和",让:当前和 - 旧和 = k,也就是,旧和 = 当前和 - k

所以代码的思路是:

初始化map = { 0:1 }sum = 0,count = 0

为什么有 0?表示:还没开始时,和就是 0。

第一步:遇到 1,sum = 1,我们找:sum - k = 1 - 2 = -1,map 里没有,记录:map = {0:1, 1:1}

第二步:遇到 1,sum = 2,找:2 - 2 = 0,map 里有,说明:从开头到这里 = 2,count++,count = 1,记录:map = {0:1,1:1,2:1}

第三步:遇到 1,sum = 3,找:3 - 2 = 1,map 里有 ,说明:中间一段 = 2,count++,count = 2

最终答案2

javascript 复制代码
function subarraySum(nums, k) {
  const map = new Map();
  map.set(0, 1);

  let sum = 0;
  let count = 0;

  for (let num of nums) {
    sum += num;

    // 找过去的某个和
    if (map.has(sum - k)) {
      count += map.get(sum - k);
    }

    // 记录现在
    map.set(sum, (map.get(sum) || 0) + 1);
  }

  return count;
}
相关推荐
casual~7 分钟前
模逆元计算方法详解:扩展欧几里得算法与费马小定理
学习·算法·逆元
脚踏实地皮皮晨33 分钟前
002002002_DepandencyObject类2
开发语言·windows·算法·c#·visual studio
冻柠檬飞冰走茶2 小时前
PTA基础编程题目集 7-27 冒泡法排序(C语言实现)
c语言·开发语言·数据结构·算法
大鱼>3 小时前
因子挖掘+回测+RL交易:量化金融完整系统
人工智能·深度学习·算法·金融
c238565 小时前
《枚举算法 “翻译官”:用 enum class 给 “游游的礼盒” 算分》
c语言·c++·算法
吃好睡好便好5 小时前
MATLAB中图像的对数变换
图像处理·学习·算法·计算机视觉·matlab
noipp5 小时前
推荐题目:洛谷 P5843 [SCOI2012] Blinker 的噩梦
c语言·数据结构·c++·算法·游戏·洛谷·luogu
极客BIM工作室5 小时前
OpenCascade 倒角(Chamfer)算法完整逻辑解析
算法
冻柠檬飞冰走茶5 小时前
PTA基础编程题目集 7-20 打印九九口诀表(C语言实现)
c语言·开发语言·数据结构·算法
鱼子星_5 小时前
《算 · 法》题目解析篇(1):最近公共祖先问题,线段树,最长回文子序列
c++·算法·动态规划·递归