“前缀和”专题篇二

news2024/9/20 14:49:34

目录

和为K的子数组

和可被K整除的子数组

连续数组

矩阵区域和


和为K的子数组

题目

思路

我们可能想到的是,从头到尾扫描数组,然后分别计算以该位置为开始,一直到数组末尾,符合和为K的子数组,但是这种方法的时间复杂度是O(N^2),是会超时的,因此需要别的方法来解决。

可能又会想到利用“前缀和”的思想,但是从头到尾扫描整个数组,然后分别计算以该位置为开始,一直到数组末尾,符合和为K的子数组,这样时间复杂度依旧是O(N^2),是会超时的,因此需要别的方法来解决。

下面我们仔细分析一下,子数组问题可以通过以某个位置为结尾来分析,此时可以先计算出该位置(含该位置)之前所有数的和,这个和是确定的,要想找到以该位置为结尾且和为K的子数组,只需要找出该位置之前和为sum-K的子数组即可,该位置之前和为sum-K的子数组的数量,就是以该位置为结尾且和为K的子数组的个数,这里可以使用“前缀和”思想,不过这里存储的不再单单只是元素的和,而是每个元素的和以及对应的个数,这里需要注意的一点是,我们并不是提前计算好前缀和,而是分析到哪个位置就计算到哪个位置之前的前缀和以及其对应的个数,可以使用哈希表进行存储,方便及时查询到,并且我们可以做一些优化,因为计算前缀和只需要知道前一个位置的前缀和,因此使用一个变量就可以实现计算前缀和。

还有需要注意的是,针对上面的方法,如果所求整个数组的和为sum,那么我们会计算[0,-1]区间的数组的和,因此,我们需要考虑到这一点,处理方法是先将0存放到哈希表中,映射的值是1.

代码

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int,int> hash;
        hash[0]=1;
        int sum=0,ret=0;
        for(int x:nums){
            sum+=x;
            if(hash.count(sum-k)) ret+=hash[sum-k];
            hash[sum]++;
        }
        return ret;
    }
};
和可被K整除的子数组

题目

思路

我们可能想到的是,从头到尾扫描数组,然后分别计算以该位置为开始,一直到数组末尾,符合和可被K整除的子数组,但是这种方法的时间复杂度是O(N^2),是会超时的,因此需要别的方法来解决。

可能又会想到利用“前缀和”的思想,但是从头到尾扫描整个数组,然后分别计算以该位置为开始,一直到数组末尾,符合和可被K整除的子数组,这样时间复杂度依旧是O(N^2),是会超时的,因此需要别的方法来解决。

下面我们仔细分析一下,子数组问题可以通过以某个位置为结尾来分析,此时我们可以先计算该位置(含该位置)之前所有元素的和,题目要求是找出和可被K整除的子数组,因为该位置(含该位置)之前所有元素的和是确定的,如果找出以该位置为结尾,和可被K整除的子数组,假设该位置(含该位置)之前所有元素的和是sum,除了和可被K整除的子数组之外元素的和是sum-n*k,那么根据《同余定理》就有sum%k=(sum-n*k),即我们只需找出该位置之前余数为sum%K的子数组的个数即可,这里需要注意的是,我们不再是先提前计算好前缀和,而是求到哪个位置就计算到哪个位置的前缀和,这里使用变量来代替之前的数组,因为计算前缀和只会用到前一个位置的前缀和和当前位置的元素,并且这里不再只是计算前缀和,还需要计算每个前缀和的值的余数对应的个数,使用哈希表来进行存储,这样就可以更快地查询到每个前缀和的值的余数对应的个数。

因为C++中对负数取模,得到的还是一个负数,因此我们需要做一些处理,即针对sum%K,变换成(sum%K+K)%K。

还有需要注意的是,针对上面的方法,如果所求整个数组的和为sum,那么我们会计算[0,-1]区间的数组余数为(sum%K+K)%K的个数,因此,我们需要考虑到这一点,处理方法是先将0存放到哈希表中,映射的值是1.

代码

class Solution {
public:
    int subarraysDivByK(vector<int>& nums, int k) {
        unordered_map<int,int> hash;
        hash[0%k]=1;
        int sum=0,ret=0;
        for(int x:nums){
            sum+=x;
            int a=(sum%k+k)%k;
            if(hash.count(a)) ret+=hash[a];
            hash[a]++;
        }
        return ret;
    }
};
连续数组

题目

思路

我们可能想到利用“前缀和”的思想,但是这道题是01序列,利用“前缀和”思想并不能知道具体有多少个0,因此我们需要再分析分析,我们不妨将原始数组中的0替换成 -1,这样找出的数组是1和 -1能够相互抵消的。

解决这道题时,我们使用“前缀和”时,不能先提前计算好前缀和,而是分析到哪个位置就把前缀和计算到哪个位置,因为计算每个位置的前缀和只会用到前一个位置的前缀和以及当前位置的值。

需要注意的是,因为题目要求含有相同数量的01的子数组的最长长度,因此下面在计算前缀和时还需要记录每个前缀和值对应的区间末尾最小下标,即如果再次遇到相同前缀和值的时候,不再记录,只记录前缀和值首次出现的区间末尾下标。

代码

class Solution {
public:
    int findMaxLength(vector<int>& nums) {
        unordered_map<int,int> hash;
        hash[0]=-1;
        int sum=0,ret=0;
        for(int i=0;i<nums.size();i++){
            sum+=nums[i]==0?-1:1;
            if(hash.count(sum)) ret=max(ret,i-hash[sum]);
            else hash[sum]=i;
        }
        return ret;
    }
};
矩阵区域和

题目

思路

这道题如果使用暴力解法的话,即针对针对查询,算出本次查询的区域,然后再计算出该区域所有数的和,但是这种方法的时间复杂度是O(N*M*Q),是会超时的,因此需要别的方法来解决。

下面将依旧使用“前缀和”的思想来解决这道题,即预先计算出每个位置和左上角构成的矩形的值的总和,针对每次查询,就可以使用O(1)的时间复杂度计算出所查询区域的值的总和。

【1】计算好每个位置和左上角构成的矩形的值的总和

【2】计算出所查询区域的值的总和

其实快速解决这道题是利用二维前缀和,只不过这道题要处理一些边界情况,因为下标[i-k],[i+k],[j-k],[j+k]是有可能超过二维前缀和矩阵的大小的,需要特别处理一下。

代码

class Solution {
public:
    vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int k) {
        int m=mat.size(),n=mat[0].size();
        vector<vector<int>> dp(m+1,vector<int>(n+1));
        vector<vector<int>> answer(m,vector<int>(n));
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+mat[i-1][j-1];
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++){
                int x1=max(1,i-k+1),y1=max(1,j-k+1);
                int x2=min(m,i+k+1),y2=min(n,j+k+1);
                answer[i][j]=dp[x2][y2]-dp[x1-1][y2]-dp[x2][y1-1]+dp[x1-1][y1-1];
                // answer[i][j]=dp[min(m,i+k+1)][min(n,j+k+1)]-dp[max(0,i-k)][min(n,j+k+1)]-dp[min(m,i+k+1)][max(0,j-k)]+dp[max(0,i-k)][max(0,j-k)];
            }
        return answer;
    }
};

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

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

相关文章

线上研讨会 | CATIA助力AI提升汽车造型设计

报名链接&#xff1a; 2024探索之旅第二季

Linux Shell基础常用脚本命令及应用案例

文章目录 常用的 Shell 命令1. 变量2. 注释3. 输出4. 输入5. 条件判断6. 循环7. 函数8. 运算9. 流程控制10. 文件和目录操作11. 错误处理 Shell 脚本应用案例1. Hello World 脚本2. 创建系统账户及设置密码3. 日志文件备份4. 一键部署 LNMP 环境5. 检查磁盘空间6. 自动安装软件…

Nginx反向代理的使用场景

Nginx Vue使用npm命令打包&#xff1a;npm run build Nginx的定位&#xff1a;主要用于做反向代理&#xff0c;一般都是用它来做前端页面的服务器&#xff0c;动态资源代理到后端服务器。这样做的好处是可以避免跨域请求带来的不便。 我们知道&#xff0c;在前端我们开发的时…

三、AI工作流(低代码)的趋势即将崛起,输入-按钮组件详解,带你轻松玩转按钮组件

对工作流感兴趣的小伙伴可以去试一试。&#x1f525;偷偷的告诉你&#xff0c;它的GPTo4.0 不要&#x1f4b0;。传送门&#xff1a;https://www.nyai.chat/chat?invitenyai_1141439 一、能用AI工作流介绍 能用AI-工作流是一个“低代码”工具、它也是个人或者中小企业的提效工…

C#语言基础速成Day07

“知止而后有定&#xff0c;定而后能静&#xff0c;静而后能安&#xff0c;安而后能虑&#xff0c;虑而后能得。” 目录 前言文章有误敬请斧正 不胜感恩&#xff01;||Day07 C#常见数据结构&#xff1a;1. 集合&#xff08;Collection&#xff09;1.1 **List<T>**1.2 **H…

MATLAB 样条插值

订阅专栏后,复制完整代码到MATLAB上面,即可获得跟本文相同的运行结果。 点击以下链接也可下载: https://download.csdn.net/download/callmeup/89635701 MATLAB插值代码 插值在MATLAB里面很简单,一个函数即可。 本文给出了已知点的坐标、待插值点的横坐标,可按要求插出来…

使用 Gradio 开发 ChatBot

Gradio 提供了 ChatInterface 组件&#xff0c;组件包括一个输入框、一个 ChatBox 区域、和一些按钮。同 interface&#xff0c;ChatInterface 通过一个处理函数进行处理&#xff0c;处理函数包括两个参数 message 和 history&#xff0c;message 是当前用户提交的问题&#xf…

[图解]需要≠需求-《分析模式》漫谈

1 00:00:00,760 --> 00:00:02,910 今天的《分析模式》漫谈 2 00:00:02,920 --> 00:00:04,180 我们来说一下 3 00:00:04,490 --> 00:00:06,490 需要不等于需求 4 00:00:10,490 --> 00:00:11,760 还是第一章 5 00:00:13,120 --> 00:00:15,020 这里 6 00:00:1…

[C#]实现GRPC通讯的服务端和客户端实例

最近要做两个软件之间消息的通讯&#xff0c;学习了一下GRPC框架的通讯。根据官方资料做了一个实例。 官方资料请参考&#xff1a;Create a .NET Core gRPC client and server in ASP.NET Core | Microsoft Learn 开发平台&#xff1a;Visual Studio 2022 开发前提条件&#x…

llama的神经网络结构;llama的神经网络结构中没有MLP吗;nanogpt的神经网络结构;残差是什么;残差连接:主要梯度消失

目录 解释代码 潜在问题和修正 结论 llama的神经网络结构 神经网络结构概述 举例说明 llama的神经网络结构中没有MLP吗 nanogpt的神经网络结构 1. 词嵌入层(Embedding Layer) 2. Transformer编码器层(Transformer Encoder Layer) 3. 层归一化(Layer Normalizat…

Linux文本处理常见工具

文章目录 文件内容查看查看文本文件内容cattacrevnl 查看非文本文件内容hexdumpodxxd 分页查看文件内容moreless 显示文本前后的行内容headtail文件描述符如果找到文件描述符 查看最新日志范例&#xff1a;找出IP地址的那一行 cut--按列抽取文本按分隔符按字符位置取网卡ip tr-…

Rocky系统部署k8s1.28.2单节点集群(Containerd)+Kuboard

目录 Kubernetes介绍 Kubernetes具备的功能 Kubernetes集群角色 Master管理节点组件 Node工作节点组件 非必须的集群插件 Kubernetes集群类型 Kubernetes集群规划 集群前期环境准备 开启Bridge网桥过滤 关闭SWAP交换分区 安装Containerd软件包 K8s集群部署方式 集…

关于归并排序:

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_urlhttps%3A%2F return 语句开始之后&#xff0c;会执行之前剩余遗留下的语句和状态#include<bits/stdc.h> using namespace std…

Xilinx XAPP585相关

XAPP585中相关的状态机 第一个状态机&#xff1a;这里主要是在对时钟线延迟的基础上&#xff0c;通过BITSLIP操作&#xff0c;做时钟的对齐&#xff1b; 第二个状态机&#xff1a;这里对c_delay_in所做的操作&#xff0c;主要是对时钟线的延迟进行控制&#xff1b; delay_con…

远程代码执行漏洞

1.简介 远程代码执行(remote code execution)简称RCE&#xff0c;由于应用程序在调用一些能够将字符串转换为代码的函数(如PHP中的eval)时&#xff0c;没有考虑用户是否控制这个字符串&#xff0c;则会导致代码执行漏洞的发生Webshell能够执行代码&#xff0c;本质上就是利用了…

新AI工程师Genie强势来袭,84秒解决代码问题

&#x1f989; AI新闻 &#x1f680; 新AI工程师Genie强势来袭&#xff0c;84秒解决代码问题 摘要&#xff1a;新兴AI软件工程师Genie因其超凡能力而引发关注&#xff0c;它在SWE-Bench排行榜上以30.07%的问题解决率远超第二名。Genie能模拟人类工程师的思维&#xff0c;自动…

CV党福音:YOLOv8实现语义分割(一)

前面我们得知YOLOv8不但可以实现目标检测任务&#xff0c;还包揽了分类、分割、姿态估计等计算机视觉任务。在上一篇博文中&#xff0c;博主已经介绍了YOLOv8如何实现分类&#xff0c;在这篇博文里&#xff0c;博主将介绍其如何将语义分割给收入囊中。 YOLOv8语义分割架构图 …

LeetCode - 54 - 螺旋矩阵

力扣54题 题目描述&#xff1a; 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 题解思路&#xff1a; 54题和59题 螺旋矩阵Ⅱ 有些微区别&#xff0c;59是nn的方形矩阵&#xff0c;但是54需要考虑行和列不相等的情况…

Webpack中搭建本地服务dev-server

开发过程中关于实现文件内容发生变化时&#xff0c;可监听文件变化内容、自动完成编译热更新&#xff0c;webpack提供了几种可选方式&#xff1a; 1. webpack watch mode监听文件变化 watch可在导出配置中添加或者在webpack 启动命令中添加--watch 注意&#xff1a;watch 的配…

武汉流星汇聚:跨境电商引领外贸增长新引擎,展望未来发展趋势

在过去的几年里&#xff0c;跨境电商如同一股强劲的东风&#xff0c;不仅为外贸增长注入了新的活力&#xff0c;更成为了引领全球贸易发展的新引擎。随着全球经济逐渐复苏&#xff0c;跨境电商行业正以惊人的速度迈向新的高度&#xff0c;展现出其作为外贸增长关键推动力的巨大…