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

news2024/11/22 16:40:48

文章目录

  • 引言
  • 和为 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.coloradmin.cn/o/1326770.html

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

相关文章

985等高校急速开设“鸿蒙班”,引领IT就业新时代

​根据澎湃新闻记者了解到&#xff0c;华为以及鸿蒙系软件厂商都在积极培养鸿蒙开发人才。其中产学联动、产教融合来培养鸿蒙生态人才是重要的一条路径&#xff0c;目前已有 23 家 985 高校、46 家 211 高校已开设或即将开设HarmonyOS 相关课程。 其中南京大学已经将 HarmonyOS…

一套rk3588 rtsp服务器推流的 github 方案及记录 -03(完结)

opencv 解码记录 解码库使用的时候发现瑞芯微以前做过解码库对ffmpeg和gstreamer的支持 然后最近实在不想再调试Rtsp浪费时间了&#xff0c;就从这中间找了一个比较快的方案 ffmpeg 带硬解码库编译 编译流程参考文献 https://blog.csdn.net/T__zxt/article/details/12342435…

【网络安全】—Shell编程入门(2)

文章目录 循环控制语句函数知识精讲数组知识精讲开发环境规范调试优化实践自动化实战项目 在前面的章节中&#xff0c;我们已经介绍了Shell编程的基础知识&#xff0c;包括变量、特殊变量、数值计算、条件测试、条件判断和基本的循环语句。接下来&#xff0c;我们将深入讲解更高…

还在用QQ拼音输入法吗?赶快卸载吧~!

最近总觉得我的C盘在莫名其妙的减少。之前的电脑C盘只有240G&#xff0c;所以我很在意C盘空间。但是&#xff0c;我发现买了新电脑&#xff0c;C盘空间也在莫名其妙减少。 随挨个文件夹检查。最后发现&#xff0c;QQ拼音的 dict 文件夹很大&#xff0c;居然有 30G多G。 30多~…

华为安防监控摄像头

华为政企42 华为政企 目录 上一篇华为政企城市一张网研究报告下一篇华为全屋wifi6蜂鸟套装标准

Linux学习(3)——基本命令-文件

1、cat&#xff1a;查看文件内容--上下合并文件 注意&#xff1a;cat只能查看普通的文本文件 如果文件内容过多会显示不全 选项效果-n显示行号包括空行-b跳过空白行编号&#xff1b;注意&#xff0c;在一行打了空格不算空白行&#xff0c;enter键直接跳过这一行才算-s将所有连续…

智能优化算法应用:基于饥饿游戏算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于饥饿游戏算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于饥饿游戏算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.饥饿游戏算法4.实验参数设定5.算法结果6.…

本地配置Java支付宝沙箱环境模拟支付并内网穿透远程调试

文章目录 前言1. 下载当面付demo2. 修改配置文件3. 打包成web服务4. 局域网测试5. 内网穿透6. 测试公网访问7. 配置二级子域名8. 测试使用固定二级子域名访问 前言 在沙箱环境调试支付SDK的时候&#xff0c;往往沙箱环境部署在本地&#xff0c;局限性大&#xff0c;在沙箱环境…

常见的Web攻击手段分析总结,实战案例:通过 X-Forwarded-Host 的密码重置令牌泄漏

常见的Web攻击手段分析总结,实战案例:通过 X-Forwarded-Host 的密码重置令牌泄漏。 常见的 Web 攻击手段主要有 XSS 攻击、CSRF 攻击、SQL 注入攻击、DDos 攻击、文件漏洞攻击等。这几种攻击方式的防护手段并不复杂,却还是有很多企业遭受了该攻击,朔源到头,还是因为人为的…

LeetCode 热题100——单调栈

​ 个人主页&#xff1a;日刷百题 系列专栏&#xff1a;〖C语言小游戏〗〖Linux〗〖数据结构〗 〖C语言〗 &#x1f30e;欢迎各位→点赞&#x1f44d;收藏⭐️留言&#x1f4dd; ​ ​ 写在前面&#xff1a; 递增单调栈&#xff1a;栈中元素从栈底到栈顶依次增大 递减单调栈…

SE-Net:Squeeze-and-Excitation Networks(CVPR2018)

文章目录 AbstractIntroduction表征的重要性以前的方向本文提出 Related WorkDeeper ArchitectureAlgorithmic Architecture SearchAttention and gating mechanisms Squeeze-and-Excitation BlocksSqueeze: Global Information EmbeddingExcitation: Adaptive RecalibrationIn…

Temporary failure in name resolution

报错&#xff1a; 1.打开resolv.conf文件 sudo vim /etc/resolv.conf 2. 确保resolv.conf文件至少包含一个名称服务器。列出名称服务器的行应如下所示&#xff1a; 3. 保存文件并退出。 4. 接下来&#xff0c;重新启动DNS 解析器服务。运行以下命令&#xff1a; sudo syste…

androidStudio版本下载链接记录

androidStudio 最新官网版本&#xff1a; 下载 Android Studio 和应用工具 - Android 开发者 | Android DevelopersAndroid Studio 提供了一些应用构建器以及一个已针对 Android 应用进行优化的集成式开发环境 (IDE)。立即下载 Android Studio。https://developer.android.g…

创建型模式 | 原型模式

一、原型模式 1、原理 原型模式&#xff0c;用原型实例指定创建对象的种类&#xff0c;并且通过拷贝这些原型创建新的对象。原型模式其实就是从一个对象再创建另外一个可定制的对象&#xff0c;而且不需要知道任何创建的细节。原型像是一个模板&#xff0c;可以基于它复制好多…

二叉树题目:输出二叉树

文章目录 题目标题和出处难度题目描述要求示例数据范围 前言解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;输出二叉树 出处&#xff1a;655. 输出二叉树 难度 6 级 题目描述 要求 给定二叉树的根结点 root \textt…

探索未来交通!空客、宝马开启新一轮“量子计算挑战赛”

12月6日&#xff0c;空中客车公司和宝马集团共同发起了一项名为 “量子交通探索”的全球量子计算挑战赛&#xff0c;以应对航空和汽车领域最紧迫的挑战——这些挑战对于传统计算机而言仍然是难以克服的。 这项挑战是首创性的&#xff0c;它将两个全球行业领导者聚集在一起&…

堆的时间复杂度

1、堆排序的时间复杂度为O(nlogn) 2、对N个元素建堆的时间复杂度为O(N)&#xff0c;删除堆顶元素的时间复杂度为O(logN)&#xff0c;因此删除堆所有元素的时间复杂度为O(NlogN)。 3、不管数组初始时是有序的还是逆序的&#xff0c;堆排序都会先建堆&#xff0c;变成了堆序的性…

《每天一分钟学习C语言·五》

1、 给一个字符数组输入字符串 char arr[10]; gets[arr]; //gets函数接收回车符&#xff0c;如果直接按回车&#xff0c;gets函数会把回车符转变成空字符作为结束&#xff0c;即arr[0]’\0’;2、 文件结尾标志ctrlz表示返回NULL 自己定义的头文件里面一般有宏定义和声明&#…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Button按钮组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Button按钮组件 一、操作环境 操作系统: Windows 10 专业版 IDE:DevEco Studio 3.1 SDK:HarmonyOS 3.1 二、Button按钮组件 Button 组件也是基础组件之一&#xff0c;和其它基础组件不…

QT打包exe文件,在其它电脑里双击exe就可以直接运行

想要不依赖QT环境&#xff0c;在其它电脑里直接双击exe文件就可以运行当前程序。具体打包过程如下&#xff1a; 使用QT编译出release版本的exe release版本运行无误后&#xff0c;需要找到当前构建生成的exe所在文件夹 可以看到具体目录在这里 我在该目录下的bin文件夹里找到…