和可被K整除的子数组(Java详解)

目录

一、题目描述

二、题解

思路分析

具体实现

完整代码


一、题目描述

给定一个整数数组 nums 和一个整数 k ,返回其中元素之和可被 k 整除的(连续、非空) 子数组 的数目。

子数组 是数组的 连续 部分。

示例:

输入:nums = [4,5,0,-2,-3,1],k = 5

输出:7

输入:nums = [ 5 ],k = 9

输出:0

二、题解

思路分析

首先我们很容易想到暴力枚举的方法,即遍历数组,在遍历每个元素的同时向后寻找元素之和能够被k整除的子数组

暴力枚举代码如下:

class Solution {
    public int subarraysDivByK(int[] nums, int k) {
       int ret = 0;
       for(int i = 0; i < nums.length; i++){
           int sum = 0;
           for(int j = i; j < nums.length; j++){
               sum += nums[j];
               if(sum % k == 0){
                   ret++;
               }
           }
       }
       return ret;
    }
}

其时间复杂度为O(N^{2}),当输入的nums数组较大时,会超出时间限制,因此,暴力枚举方式行不通,我们继续考虑其他方法

题目中要求我们找到元素之和可被k整除的(连续、非空)子数组,因此我们可以想到使用双指针的思路,即考虑使用滑动窗口来解决这个问题,然而,本题不能使用滑动窗口来解决

为什么不能使用滑动窗口?

参照示例1,其输入的数组 nums = [4,5,0,-2,-3,1],其中不仅有正整数,还有零和负数,

在使用滑动窗口时,当窗口内元素满足条件时,要移动left指针,向前滑动窗口,但在本题中,由于有零和负整数,在窗口内元素满足条件时,不能移动left指针,因为下一个元素可能是零,加入后任满足条件,也可能几个元素相加等于0,加入后也满足条件。因此,若是使用滑动窗口来解决本题,则会漏掉一些符合情况的子数组。

滑动窗口的思路也不行,我们继续思考新的方法,在涉及子数组问题时,我们也常使用前缀和来解决问题

什么是前缀和?

前缀和即某序列的前n项和,类似于数学中的数列前n项和。即从首元素位置到i位置这个区间内所有元素之和,前缀和只是一种思路,其不仅可以求和,也可以求从首元素位置到i位置区间内的乘积等等。

我们以示例1为例子,先求前缀和数组,再通过前缀和数组来求解子数组,

然而,在这种情况下,当我们求解子数组时,仍然需要后遍历,求得从i到j位置的元素之和,再判断其是否符合条件,

其时间复杂度仍是O(N^{2})

在通过前缀和数组求解子数组时,我们可以考虑向前遍历,即i位置上的元素为到i位置的元素之和

此时,若以i位置为结尾的区间内的元素能够被被k整除,则

 此时dp[i] - dp[j] = mk,(m为系数),即dp[i]与dp[j]同余(dp[i]取余 k 与dp[j]取余 k 的余数相同)(两数余数相同,在相减时就将余数消去,剩下的数便能整除k),此时,我们只需要找到,在i位置之前有多少个前缀和元素的余数与其前缀和相同,就能够得到以i位置为结尾的且能够被k整除的子数组个数。

然而,在求i位置之前有多少个前缀和元素的余数与其相同时,我们还需要再向前遍历一遍前缀和数组吗?

我们可以使用哈希表,存储前缀和元素的余数及其个数,这样,便只需要计算dp[i]的余数,再从哈希表中找到相同余数的元素个数,就可知道以i位置为结尾的且能够被k整除的子数组个数了。

在分析完思路后,我们来考虑其具体实现过程:

具体实现

首先我们需要一个哈希表,以前缀和元素模k的值为键,值的个数为值

// key:模k的的值,value:key的个数
Map<Integer, Integer> hash = new HashMap<>();

需要注意的是,在模k时,如果元素为负数,求出的值也为负数(例如 -4 % 5 = -4,-4 与 1 是同余的,若我们在哈希表中保存(-4, 1),而 % i的结果为 1,并在哈希表中找到结果为1的元素个数,此时就漏掉了结果 为 -4 的情况),

因此我们需要对其进行处理,将其变为正数,可以将其+k,使其变成正数,即 dp[i] % k + k(-4 + 5 = 1);当其为正数的时候则不需要 +k,若想要无需对元素进行正负数判断,则可在 +k 后再取余k,即 (dp[i] % k + k) % k,此时,若元素为正数,在 +k 后结果大于k,再对结果进行取余,又将其变为正确结果((3 % 5 + 5)% 5);若元素为负数,在 +k 后将负数变为正数,即正确结果,再对结果进行取余,仍是正确结果((-4 % 5 + 5)% 5)

求出数组的前缀和数组

由于哈希表中保存的是模k的值及其个数,因此我们不需要再创建一个前缀和数组用来保存前缀和,只需使用变量sum 来保存前i-1个元素的和

何时将结果放到哈希表中?

我们要从哈希表中找到相同余数的元素个数,从而知道以i位置为结尾的且能够被k整除的子数组个数,因此哈希表中不能存放i位置之后的元素结果,因此,每遍历一个元素,就将其结果更新到哈希表中

然而,此时还有一个细节问题

若以i位置为结尾的数组本身便能被k整除,此时模k的结果为 0,即从0位置到i位置的子数组之和能够被k整除,则在第一次出现该情况时,哈希表内没有key = 0的元素,会漏掉该结果,因此,我们需要处理这种特殊情况,即手动将(0, 1)放入哈希表中

完整代码

class Solution {
    public int subarraysDivByK(int[] nums, int k) {
        // key:模k的的值,value:key的个数
       Map<Integer, Integer> hash = new HashMap<>();
       //处理特殊情况
        hash.put(0,1);
        int ret = 0;//子数组的个数
        int sum = 0;//用来保存前i-1个元素之和
        for(int i = 0; i < nums.length; i++){
            sum += nums[i];
            //求出与 前i个元素之和 同余的元素个数
            int same = hash.getOrDefault((sum % k + k) % k, 0);
            ret += same;//更新结果
            hash.put((sum % k + k) % k,same + 1);//更新哈希表
        }
        return ret;
    }
}

题目来自:

974. 和可被 K 整除的子数组 - 力扣(LeetCode)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/301220.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

什么是PD快充诱骗芯片?它的原理是什么?

PD快充诱骗芯片&#xff0c;顾名思义&#xff0c;就是通过LDR6328Q PD取电芯片把pd适配器的电压给诱骗出来固定给后端设备供电。PD诱骗芯片是受电端的一种PD协议芯片&#xff0c;它内置了PD通讯模块&#xff0c;通过与供电端&#xff08;如PD充电器&#xff09;的PD协议芯片握手…

深入理解堆(Heap):一个强大的数据结构

. 个人主页&#xff1a;晓风飞 专栏&#xff1a;数据结构|Linux|C语言 路漫漫其修远兮&#xff0c;吾将上下而求索 文章目录 前言堆的实现基本操作结构体定义初始化堆&#xff08;HeapInit&#xff09;销毁堆&#xff08;HeapDestroy&#xff09; 重要函数交换函数&#xff08;…

Eslint+Prettier

1.Eslint js验证的规则标准,Vue也有自己的独特的验证规则,vue-eslint-plugin属于vue自己的验证规则。 如果不想报错,可以在package.json/rules里面进行关闭,默认是开启的,默认缩进是两个空格。 2.Prettier - Code formatter 使写代码更加的美观 可选的配置项: 例如: module…

三代半导体材料有何区别

什么是半导体材料 半导体材料是制作半导体器件和集成电路的电子材料&#xff0c;是半导体工业的基础。利用半导体材料制作的各种各样的半导体器件和集成电路&#xff0c;促进了现代信息社会的飞速发展。 绝缘体、半导体和导体的典型电导率范围 半导体材料的研究开始于19世纪初…

GPT在地学、GIS、气象、农业、生态、环境等领域应用教程

详情点击链接&#xff1a;GPT在地学、GIS、气象、农业、生态、环境等领域应用教程 一开启大模型 1 开启大模型 1)大模型的发展历程与最新功能 2)大模型的算法构架与底层逻辑 3)大模型的强大功能与应用场景 4)国内外经典大模型&#xff08;ChatGPT、LLaMA、Gemini、DALLE、…

vscode中uniapp项目无法编译生成dist 也不报错的解决办法

就在昨天&#xff0c;我修改项目的代码UI部分后&#xff0c;执行「npm run dev:mp-weixin 」这个指令&#xff0c;开发工具中的页面没有任何变化&#xff0c;然后终端的输出如下图&#xff1a; 毫无提示&#xff0c;当下就觉得不对劲&#xff0c;果然在微信开发工具里面看到编译…

百度旋转验证码识别研究

最近研究了一下图像识别&#xff0c;一直找到很好的应用场景&#xff0c;今天我就发现可以用百度的旋转验证码来做一个实验。没想到效果还挺好&#xff0c;下面就是实际的识别效果。 1、效果演示 2、如何识别 2.1准备数据集 首先需要使用爬虫&#xff0c;对验证码图片进行采…

C++入门教程,C++基础教程(第一部分:从C到C++)七

由C语言发展而来的一种面向对象的编程语言。 第一部分、从C语言到C 本章讲述 C 语言的简史&#xff0c;以及 C 语言中与面向对象关系不大、C语言中没有的特性。这些特性能够增加编程的便利性&#xff0c;提高程序的可扩充性。 十三、如何规范地使用C内联函数 inline 关键字…

QT入门操作

1-Qt简介 Qt是什么&#xff1f; 这门课程的定位&#xff1a; C的实践课。系统性的认识图形用户界面编程新的就业方向 Qt是一个基于C的图形用户界面&#xff08;GUI&#xff09;开发框架&#xff0c;但是Qt不仅仅能开发界面&#xff0c;还包括很多传统编程中的计数&#xff1a;多…

【C语言】指针——从底层原理到应用

C语言指针-从底层原理到花式技巧&#xff0c;用图文和代码帮你讲解透彻 目录 一、前言二、变量与指针的本质 1. 内存地址2. 32位与64位系统3. 变量4. 指针变量5. 操作指针变量 5.1 指针变量自身的值5.2 获取指针变量所指向的数据5.3 以什么样的数据类型来使用/解释指针变量所指…

深入了解 Vite:快速、简洁、高效的前端构建工具(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

【Matplotlib】基础设置之图像处理05

图像基础 导入相应的包&#xff1a; import matplotlib.pyplot as plt import matplotlib.image as mpimg import numpy as np %matplotlib inline导入图像 我们首先导入上面的图像&#xff0c;注意 matplotlib 默认只支持 PNG 格式的图像&#xff0c;我们可以使用 mpimg.im…

管理系统-基于javaweb的图书管理系统

基于javaweb的图书管理系统 &#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; 本项目采用eclipse工具开发&#xff0c;jspservlet技术编写&#xff0c;样式采用了layui…

Python综合数据分析_根据订单求RFM值

文章目录 0.导入数据1.数据可视化2.数据清洗3.特征工程4.构建User用户表5.求R值6.求F值7.求M值 0.导入数据 import pandas as pd #导入Pandas df_sales pd.read_csv(订单.csv) #载入数据 df_sales.head() #显示头几行数据 1.数据可视化 import matplotlib.pyplot as plt #导…

Linux链接的创建,删除,修改

目录 1. 概述2. 硬链接2.1 创建硬链接2.2 删除硬链接 3. 软链接3.1 创建软链接3.2 删除软链接 5. 常用的终端工具下载 计算机基础–Linux详解 1. 概述 在Linux系统中&#xff0c;链接是一种文件系统中的重要概念。链接允许用户在文件系统中创建指向另一个文件的引用&#xff0c…

2024年HCIE认证有什么用?华为HCIE好考吗?

随着信息技术的迅速发展&#xff0c;网络工程师的需求越来越高&#xff0c;而HCIE作为华为认证体系中的最高级别认证&#xff0c;备受从业者关注。本文将深入研究2024年HCIE认证的价值、考试难度以及报名费用等方面的信息。 2024年HCIE认证有什么用? 新的一年即将到来&#x…

Java学习,一文掌握Java之SpringBoot框架学习文集(5)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

NGINX 配置本地HTTPS(免费证书)

生成秘钥key,运行: $ openssl genrsa -des3 -out server.key 2048 会有两次要求输入密码,输入同一个即可。输入密码然后你就获得了一个server.key文件。 以后使用此文件(通过openssl提供的命令或API)可能经常回要求输入密码,如果想去除输入密码的步骤可以使用以下命令: $ op…

2023全球软件研发技术大会(SDCon2023)-核心PPT资料下载

一、峰会简介 本次峰会包含12大会议主题&#xff1a;云原生设施与平台、微服务架构实践、软件质量与效能、大数据实践与前沿、架构设计与演进、高可用与高性能架构、Web与大前端开发、编程语言与平台、AIGC与大模型、推荐系统实践、AI智能应用与研究、机器学习架构实践。 软件…

一款好用的漏洞扫描工具

APIDetector 是一款强大而高效的工具&#xff0c;旨在测试各个子域中公开的 Swagger 端点&#xff0c;并具有独特的智能功能来检测误报。对于从事 API 测试和漏洞扫描的安全专业人员和开发人员来说特别有用。 功能&#xff1a; 灵活输入&#xff1a;接受文件中的单个域或子域列…