【LeetCode刷题笔记(11-1)】【Python】【和为 K 的子数组】【前缀和】【中等】

文章目录

  • 引言
  • 和为 K 的子数组
    • 题目描述
    • 提示
  • 解决方案1:【暴力枚举】
  • 解决方案2:【前缀和】
  • 结束语

和为 K 的子数组


引言

编写通过所有测试案例的代码并不简单,通常需要深思熟虑理性分析。虽然这些代码能够通过所有的测试案例,但如果不了解代码背后的思考过程,那么这些代码可能并不容易被理解和接受。我编写刷题笔记的初衷,是希望能够与读者们分享一个完整的代码是如何在逐步的理性思考下形成的。我非常欢迎读者的批评和指正,因为我知道我的观点可能并不完全正确,您的反馈将帮助我不断进步。如果我的笔记能给您带来哪怕是一点点的启示,我也会感到非常荣幸。同时,我也希望我的分享能够激发您的灵感和思考,让我们一起在编程的道路上不断前行~


和为 K 的子数组

题目描述

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

解决方案1:【暴力枚举】

根据题意,我们需要统计数组nums和为k的子数组的个数。为了做到这一点,一种直接方法是遍历所有子数组,然后检查每个子数组的和是否等于k

完整代码如下

class Solution:  def subarraySum(self, nums: List[int], k: int) -> int:  # 初始化计数器为0  count = 0  # 获取数组的长度  n = len(nums)  # 遍历数组  for i in range(n):  # 初始化tmp_sum为0  tmp_sum = 0  # 遍历当前元素之后的数组  for j in range(i, n):  # 累加当前元素到tmp_sum  tmp_sum += nums[j]  # 如果tmp_sum等于k,则计数器加1  if tmp_sum == k:   count += 1  # 返回最终的计数结果  return count

运行结果
在这里插入图片描述

虽然这种方法很直接,但它的效率并不高,因为它涉及到两层循环的暴力枚举,时间复杂度为O(n2), 不能通过所有的测试用例。

问题1:从运行结果来看,暴力枚举算法应该存在巨大的优化空间,代码哪些部分可以进一步优化呢?

暴力枚举算法简单粗暴,如果能够优化,一定是在两层遍历中找到优化点! ⇒ 拆解for循环,尝试找到优化点

我们将sum(i --> j)定义为子数组nums[i: j+1]的和(即包括位置j)

  • i=0时,tmp_sum可以动态记录sum(0 --> j),其中j0 —> n-1
  • i为区间[1, n-1]的任意值时,tmp_sum可以动态记录sum(i --> j),其中 ji —> n-1。 对于任意的jsum(i --> j) 等价于 sum(0 --> j) - sum(0 --> i-1),更关键的是,sum(0 --> j)sum(0 --> i-1)已经在i=0时就已经计算出来了 ⇒ 只需要知道所有的sum(0 --> j) ,其中j0 —> n-1,就可以算出任意区间[i, j]的子数组和sum(i --> j)!!!

问题2:通过拆解for循环,我们知道用好sum(0 --> j)是进一步优化算法的关键,那么基于sum(0 --> j)的算法有没有约定俗成的名称?

有,[sum(0 --> j), for j in range(n)]实际上就是数组nums前缀和数组!

解决方案2:【前缀和】

问题3:现在我们已知前缀和数组[sum(0 --> j), for j in range(n)],如何找到满足和为k的所有子数组呢?

首先,明确核心目标:找到所有满足和为k的所有子数组的个数

当遍历到nums的第i个元素时,我们已知

  1. sum(0 --> j), j从0 --> i的所有情况 ;
  2. 区间[0, i]内的任意以i为终止位置的子区间[j ,i]的和都可以通过sum(0 --> i) - sum(0 --> j)获取;

那么对于以i为终止位置的任意子区间[j ,i],只要sum(0 --> i) - sum(0 --> j) = k成立,那么都是我们要找的子数组。如果我们提前用字典数据结构pre_sum_dict存储所有出现过的前缀和,以为键,以和出现的次数为值 ⇒ 查找sum(0 --> i) - k 是否存在于 pre_sum_dict, 若存在,且pre_sum_dict[sum(0 --> i) - k]的值为N ⇒ 找到了N个i为终止位置的子区间[j ,i],满足sum(0 --> i) - sum(0 --> j) = k

通过一次for循环,i从0取到n-1,我们就可以得到每个循环下所有以i为终止位置且满足和为k的子数组个数,用count作为计数器进行计数即可得到满足和为k的所有子数组的个数。

完整代码如下

class Solution:  def subarraySum(self, nums: List[int], k: int) -> int:  # 初始化计数器为0  count = 0  # 获取数组的长度  n = len(nums)  # 创建一个字典用于存储前缀和及其出现的次数  pre_sum_dict = {}  # 初始化前缀和为0的次数为1  pre_sum_dict[0] = 1  # 初始化前缀和为0  cur_pre_sum = 0  # 遍历数组  for i in range(n):  cur_pre_sum += nums[i] # 以i为结束位置的数组nums[:i+1]的和# 如果前缀和减去目标值在之前的前缀和中出现过  if cur_pre_sum - k in pre_sum_dict:  # 将出现次数加入计数器  count += pre_sum_dict[cur_pre_sum - k]  # 如果前缀和不在之前的前缀和中出现过  if cur_pre_sum not in pre_sum_dict:  # 将前缀和加入字典并设置出现次数为1  pre_sum_dict[cur_pre_sum] = 1  else:  # 否则将前缀和的出现次数加1  pre_sum_dict[cur_pre_sum] += 1  return count

运行结果
在这里插入图片描述

复杂度分析

  • 时间复杂度:O(n), n为数组nums的元素个数。
  • 空间复杂度:O(n),哈希字典需要存放n个前缀和。

结束语

  • 亲爱的读者,感谢您花时间阅读我们的博客。我们非常重视您的反馈和意见,因此在这里鼓励您对我们的博客进行评论。
  • 您的建议和看法对我们来说非常重要,这有助于我们更好地了解您的需求,并提供更高质量的内容和服务。
  • 无论您是喜欢我们的博客还是对其有任何疑问或建议,我们都非常期待您的留言。让我们一起互动,共同进步!谢谢您的支持和参与!
  • 我会坚持不懈地创作,并持续优化博文质量,为您提供更好的阅读体验。
  • 谢谢您的阅读!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL进阶理论篇(十七):数据库主从同步的原理

文章目录 简介为什么需要主从同步主从同步的原理总结参考文献 简介 以MySQL数据库为例&#xff0c;在实际生产中&#xff0c;我们会如何对MySQL数据库进行性能优化呢&#xff1f; 比如说配合上Redis做缓存。Redis是一种高性能的内存数据库&#xff0c;而MySQL是一种基于磁盘文…

docker-compose安装Rocketmq总结,以及如何更换mq端口

默认你已经装好了docker哈 安装docker-compose sudo curl -L https://github.com/docker/compose/releases/download/1.25.1-rc1/docker-compose-uname -s-uname -m -o /usr/local/bin/docker-composechmod x /usr/local/bin/docker-composedocker-compose --version成功打印…

截断霍夫曼编码

截断霍夫曼编码是一种数据压缩技术&#xff0c;它基于霍夫曼编码的原理&#xff0c;通过截断霍夫曼树&#xff0c;减少编码中的冗余信息&#xff0c;实现更高效的数据压缩。在本文中&#xff0c;我们将详细探讨截断霍夫曼编码的原理、应用及其优势。 一、霍夫曼编码简介 霍夫曼…

12.21 汇编点亮STM32MP157小灯

.text .global _start _start: 时钟使能pb6 pf6 pe9LDR r0,0x50000A28LDR r1,[r0]ORR r1,r1,#(0x1<<4)ORR r1,r1,#(0x1<<5)ORR r1,r1,#(0x1<<1)STR r1,[r0]配置GPIO模式LDR r0,0x50006000LDR r1,[r0]BIC r1,r1,#(0x2<<20)ORR r1,r1,#(0x1<<20)B…

kubernetes集群应用 service进阶

kubernetes集群应用 Service进阶 一、场景 使用kubernetes集群运行工作负载时&#xff0c;由于Pod经常处于用后即焚状态&#xff0c;Pod对应的IP地址也会经常变化&#xff0c;因此我们不能直接访问Pod&#xff0c;可以通过Service对应的端点列表&#xff08;Endpoints&#x…

PaddleOCR Docker 容器快捷调用,快捷调用OCR API

文章目录 搞环境命令行测试Python调用测试转fastapi服务打包成镜像服务PaddleOCR 服务端模型总结&#xff0c;直接启动OCR服务 paddleOCR迎来大更新&#xff0c;搞一把新的api接口&#xff0c;直接用起来。 搞环境 搞容器&#xff1a; FROM nvidia/cuda:11.8.0-cudnn8-devel…

Python importlib模块详细教程

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com importlib模块是Python标准库中用于动态导入模块的工具。它提供了一系列函数&#xff0c;允许以编程方式加载、检查和操作模块。本文将深入探讨importlib的各种用法&#xff0c;并通过丰富的示例代码帮助你更好地…

华清作业day46

.text .global _start _start: led1 设置时钟使能 ldr r0,0x50000A28 ldr r1,[r0] orr r1,r1,#(0x1<<4) str r1,[r0]设置输出模式 ldr r0,0x50006000 ldr r1,[r0] bic r1,r1,#(0x3<<20) orr r1,r1,#(0x01<<20) str r1,[r0]设置推挽输出 ldr r0,0x5000600…

在QT Creator下用CMake编译GEOS库

最近&#xff0c;想要在C下编一个可用GDAL模块的地图管理系统&#xff0c;找来找去&#xff0c;找到了GEOS。GEOS&#xff08;Geometry Engine-Open Source&#xff09;开源几何引擎 是一个用于计算几何的JTS库的 C/C实现&#xff0c;专注于地理信息系统 &#xff08;GIS&#…

速通Python基础语法--语句篇

缩进和代码块 一 条件语句if/elif if的基本语法 示例 条件语句嵌套 练习1 练习2 二 空语句 三 while循环 示例 打印1-10 求1-100的和 求5! 求1-5的阶乘之和 四 for循环 for的基本语法 1~range[ ,) 五 continue/break continue:结束当前循环,继续下一次循环 break:结束整个循…

《每天一分钟学习C语言·四》文本读写操作及二进制读写

fopen(参数1,参数2)&#xff0c;第一个参数是要打开的文件名&#xff0c;文件名字符串&#xff0c;第二个参数用于制定文件打开模式的一个字符串。 注&#xff1a;如果要打开某个盘的文本如F盘test文件夹下的test.txt文本&#xff0c;则fopen(“F:\test\test.txt”,”r”); 程序…

AcWing算法进阶课-1.1.2Dinic/ISAP求最大流

算法进阶课整理 CSDN个人主页&#xff1a;更好的阅读体验 原题链接 题目描述 给定一个包含 n n n 个点 m m m 条边的有向图&#xff0c;并给定每条边的容量&#xff0c;边的容量非负。 图中可能存在重边和自环。求从点 S S S 到点 T T T 的最大流。 输入格式 第一行包…

本地websocket服务端结合cpolar内网穿透实现公网访问

文章目录 1. Java 服务端demo环境2. 在pom文件引入第三包封装的netty框架maven坐标3. 创建服务端,以接口模式调用,方便外部调用4. 启动服务,出现以下信息表示启动成功,暴露端口默认99995. 创建隧道映射内网端口6. 查看状态->在线隧道,复制所创建隧道的公网地址加端口号7. 以…

黑马头条--day07--app文章搜索

目录 一.安装elasticsearch 1.拉取镜像 2.创建存放数据及配置文件的文件夹&#xff0c;启动时挂载。 4.修改文件夹权限 5.启动容器 5.1参数解释 6.安装ik分词器 6.2测试一下Ik分词器 二.添加文章索引库 1查询所有的文章信息&#xff0c;批量导入到es索引库中 2)测试 …

深度盘点:除了BRC20外 这些公链潜力铭文也值得关注

近日的铭文市场风起云涌&#xff0c;除BRC20占据着市场70%以上的份额外&#xff0c;其他公链的铭文也在快速发展

Spring Boot + EasyUI 全屏布局(二)

一、创建一个Spring Boot EasyUI项目 Spring Boot EasyUI 创建第一个项目&#xff08;一&#xff09;_springboot整合easyui-CSDN博客 二、相关知识点总结 布局&#xff08;layout&#xff09;是有五个区域&#xff08;北区 north、南区 south、东区 east、西区 west 和中区…

Spring Boot学习随笔- 拦截器实现和配置(HandlerInterceptor、addInterceptors)、jar包部署和war包部署

学习视频&#xff1a;【编程不良人】2021年SpringBoot最新最全教程 第十三章、拦截器 拦截器 &#xff1a;Interceptor 拦截 中断 类似于javaweb中的Filter&#xff0c;不过没有Filter那么强大 作用 Spring MVC的拦截器是一种用于在请求处理过程中进行预处理和后处理的机制。拦…

typeScript安装及TypeScript tsc 不是内部或外部命令,也不是可运行的程序或批处理文件解决办法

一、typeScript安装&#xff1a; # 全局安装 TypeScript npm i -g typescript 二、检查是否安装成功ts&#xff1a; #检查ts的版本号 确定是否安装成功 tsc -v出现报错&#xff1a;‘tsc’ 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 解决&#xff1…

fastGitHub工具推荐(如果打不开github或者使用很慢可以使用该工具)

目录 一&#xff0c;针对问题二&#xff0c;下载1&#xff0c;github里面下载FastGitHub2&#xff0c;博客上传了下载资源 三&#xff0c;安装使用点击执行文件即可 一&#xff0c;针对问题 当使用github很慢&#xff0c;或者根本打不开的时候&#xff0c;就可以使用该工具 …

Java基础知识复习

目录 一、Java语言基础知识&#xff0c;包括面向对象编程、语法特性等 0、什么是面向对象编程&#xff1f; 1、基本语法&#xff1a; 2、变量和数据类型&#xff1a; 3、运算符和表达式&#xff1a; 4、控制结构&#xff1a; 5、函数和方法&#xff1a; 6、类和对象&#xff1a…