leetcode 560. 和为 K 的子数组(优质解法)

2023-12-19

代码:

class Solution {
    public int subarraySum(int[] nums, int k) {
        int length=nums.length;
        // key 表示前缀和,value 表示个数
        HashMap<Integer,Integer> hashMap =new HashMap<Integer,Integer>();
        //默认有一个前缀和为 0 的数据,解决下标前缀和直接为 0 的特殊情况
        hashMap.put(0,1);

        int last=0; //前一个下标的前缀和
        int now=0;  //当前下标的前缀和
        int count=0;    //记录符合条件的子数组个数
        for(int i=0;i<length;i++){
            now=last+nums[i];
            int find=now-k; //计算要在哈希表中查找的前缀和
            count+=hashMap.getOrDefault(find,0);
            //将当前下标的前缀和添加到哈希表中
            hashMap.put(now,hashMap.getOrDefault(now,0)+1);
            last=now;
        }

        return count;

    }
}

题解:

本题的题意很清晰,需要统计出 该数组中和为 k 的子数组的个数

要注意题目给出的数据范围是 -1000 <= nums[i] <= 1000, 所以数组中存在小于等于 0 的数据

先来思考一下本题的暴力解法,我们将所有的子数组遍历出来,统计出其中 和为 k 的子数组的个数 即可,时间复杂度为 O(n^2),这是一个很大的时间复杂度,所以我们需要进行优化

本题可以用前缀和的方式来进行优化,定义一个前缀和数组 sum,sum[ i ] 代表从 0 ~ i 的数据总和,为了便于理解,我画了如下的图:

如上图,我们要统一以下标 i 为尾的符合条件的子数组个数,就需要在 0~ i -1 中找到下标 j ,使 j 到 i 之间数据和为 k,即我们要 0~ i -1 找到 j 下标使 sum[ j-1 ] = sum [ i ] - k ,找到多少个符合条件的 j 下标就代表以下标 i 为尾的符合条件的子数组个数有多少个,更简单来说就是, 在 0~ i -1 中有多少个下标的前缀和 = sum [ i ] - k ,就代表以下标 i 为尾的符合条件的子数组个数有多少个

我们可以将已经获取到的前缀和记录到哈希表中,前缀和为 key ,个数为 value,记录在 i 下标之前,各个前缀和对应的个数

以 nums = 1,2,3  k = 3 为例,i 一开始指向 0 下标,前缀和 sum[ 0 ] = 1,我们要查找的前缀和是 sum [ 0 ] - k = 1 - 3 = -2,在哈希表中没有 -2 这个前缀和对应的数目,所以没有符合条件的子数组,i 向下遍历,将当前的 前缀和记录到哈希表中

1        2        3                        哈希:

key = 1,value =1

i

前缀和 sum[ 1 ] = 3,我们要查找的前缀和是 sum [ 1 ] - k = 3 - 3 = 0,在哈希表中没有 0 这个前缀和对应的数目,但实际上现在 0~i 之间的子数组已经是满足要求的了,所以我们这里没有考虑到  sum [ i ] - k = 0 的特殊情况,所以一开始创建哈希表时就应该添加 key = 0,value =1(前缀和为 0 的下标有一个) 这个数据

此时在哈希表中就获取到了0 这个前缀和对应的数目 1 ,我们便得到以 1 下标为尾的符合条件的子数组个数为 1,将其记录到 count 中,将当前的 前缀和记录到哈希表中

1        2        3                        哈希:

i key = 0,value =1

key = 1,value =1

key = 3,value =1

i 继续向下遍历, 前缀和 sum[ 2 ] = 6,我们要查找的前缀和是 sum [ 2 ] - k = 6 - 3 = 3,在哈希表中 前缀和为 3 的下标有 1 个,所以 便得到以 2 下标为尾的符合条件的子数组个数为 1,将其记录到 count 中,将当前的 前缀和记录到哈希表中

1        2        3                               哈希:

i key = 0,value =1

key = 1,value =1

key = 3,value =1

key = 6,value =1

而要获取当前 i 下标的前缀和很容易,我们在获取 i 下标的前缀和就已经知道 i - 1 下标的前缀和了,所以 sum[ i ] = sum[ i-1 ] + nums[ i ] ,提前设置好 0 下标之前前缀和为 0 即可

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

leetcode 560. 和为 K 的子数组(优质解法) 的相关文章

随机推荐

  • 低代码助力全栈开发

    目录 低代码功能展示 1 拖拽式 UI 组件 2 更快的开发速度 3 敏捷原型设计 4 与数据库集成 低代码开发工具正变得日益强大 它正不断弥合着前后端开发之间的差距 对于后端来说 基于低代码平台开发应用时 完全不用担心 前端的打包 部署
  • JavaOOP篇----第三篇

    系列文章目录 文章目录 系列文章目录 前言 一 标识符的命名规则 二 instanceof关键字的作用 三 什么是隐式转换 什么是显式转换 前言 前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住分享一下给大家 点击跳转到网
  • Linux中动态路由协议有哪些?

    Linux动态路由是一种在Linux操作系统中实现动态路由的机制 动态路由是指路由器能够根据网络的变化自动更新路由表 以实现更高效的数据传输 在Linux中 动态路由可以通过配置路由规则来实现 那么Linux中动态路由协议有哪些 以下是具体
  • kubernetes入门到进阶(2)

    被隔离的进程 一起来看看容器的本质 大家好 我们继续来一起学习k8s 在上一个章节里 我们初步了解了容器技术 在Linux虚拟机里安装了当前最流行的容器docker 还是用了docker ps docker run 等命令简单操作了容器 广
  • 【计算机图形学】PointNet文章的简单理解与运用,点云特征提取

    PointNet论文原文 PointNet Deep Learning on Point Sets for 3D Classification and Segmentation PointNet官方代码是使用tensorflow实现的 Po
  • 数据库学习日常案例20231218-oracle 19RAC hip远程注册服务到scan listener分析

    问题 用户一套Oracle19c RAC集群 出现一个奇怪的现象 通过SCAN IP访问的连接会话都集中在节点一实例 而且用户并没有做任何的节点服务访问去控制会话的连接节点 比如常见的通过集群的高可用服务去控制应用访问连接集中在同一节点 从
  • 渗透测试与安全测试主要区别是什么?

    在网络安全体系中 有很多专业术语 而且部分专业术语在名字上有很大的相似之处 因此很多小伙伴将它们混淆在一起 比如渗透测试和安全测试 这两个概念就经常被混淆在一起 那么什么是渗透测试和安全测试 有何区别 渗透测试是通过模拟恶意黑客的攻击方法
  • 转移mysql中的数据

    目录 1 mysqldump 2 将数据库中的数据转换为一个sql文件 3 执行sql文件 1 mysqldump 转移数据需要用到mysqldump 默认情况下mysqldump会自动被安装上 如果没有用不了 建议重新安装一下 参考 my
  • 4.docker镜像及相关命令

    目录 1 查看所有镜像 docker images 1 1 基本用法 1 2 docker images q 只显示所有镜像ID 1 3 docker images f 筛选条件 q 只显示符合条件的所有镜像ID 1 4 docker im
  • 在Springboot项目中使用Quartz执行定时任务

    所使用的jar包
  • C语言,scanf出错时,重新输入

    问题的关键在于 把stdin中剩余的字符 吃掉 才能正常地进行下次输入 scanf出错后重新输入 使用 n 清空错误的字符 include
  • 将yolo格式转化为voc格式:txt转xml(亲测有效)

    1 文件目录如下所示 对以上目录的解释 1 dataset下面的image文件夹 里面装的是数据集的原图片 2 dataset下面的label文件夹 里面装的是图片对应得yolo格式标签 3 dataset下面的Annotations文件夹
  • 集成测试:确保软件系统无缝协同的关键

    摘要 本文将详细介绍集成测试的概念 目的 方法和实践 通过深入探讨集成测试的重要性 以及如何有效地进行集成测试 帮助读者更好地理解和应用集成测试技术 提高软件系统的质量和稳定性 一 引言 随着软件开发过程的不断演进 软件系统变得越来越复杂
  • 各种免费的格式转换工具

    PDF转CAD或其它 Zamzar video converter audio converter image converter eBook converter
  • Arraylist与LinkedList有什么区别?

    Arraylist与LinkedList有什么区别 一个工作4年的程序员去某互联网公司面试 被问到了这个问题 如果大家不知道这个问题该怎么回答 可以在文章尾端扫码二维码领取我整理的50W字的大厂面试指南 问题分析 ArrayList和Lin
  • 模块测试:确保软件质量的关键步骤

    引言 在软件开发过程中 模块测试是确保软件质量的关键环节 通过模块化的设计和测试方法 可以提高开发效率 降低错误率 并最终提供稳定可靠的软件产品 本文将介绍模块测试的概念 重要性以及实施步骤 帮助读者了解如何有效地进行模块测试 一 什么是模
  • 5.docker容器及相关命令

    docker中的容器实际上就是宿主机中的一个进程 目录 1 创建并启动容器 docker run 1 1 如果没有指定的镜像的话 docker会尝试从源拉取 1 2 给容器起名字 name 1 3 交互方式启动 i 与弹出客户端 t 1 4
  • 软件测试之威胁分析:保护您的应用程序免受潜在风险的侵害

    引言 在当今数字化时代 软件已经成为我们日常生活和工作中不可或缺的一部分 然而 随着软件的复杂性和规模不断增加 软件测试的重要性也日益凸显 本文将重点介绍软件测试中的威胁分析 帮助您了解并应对潜在的风险 确保您的应用程序的安全性和稳定性 一
  • MCU平台下确定栈空间大小的方法

    本文介绍MCU平台下确定栈空间大小的方法 通常使用IDE开发MCU程序在生成Image文件时 Image文件被划分为代码区 数据区 BSS区 堆区 栈区 其中 代码区 数据区 BSS区空间大小由编译器最终决定 对于MCU 堆区一般设置为0
  • leetcode 560. 和为 K 的子数组(优质解法)

    代码 class Solution public int subarraySum int nums int k int length nums length key 表示前缀和 value 表示个数 HashMap