C++算法 —— 前缀和

一、【模版】前缀和

1.链接

【模板】前缀和_牛客题霸_牛客网 (nowcoder.com)

2.描述

3.思路

前缀和的思想其实就是一种简单的动态规划,以i位置记录从头位置到i位置的和,然后间接的求一段连续区间的数组和,时间复杂度是O(n) + O(q),这种思想在实际中是为了应对多次查询的情况,当q特别大时,采用这种方式的时间复杂度就会较低

4.参考代码

#include <iostream>
#include <vector>
using namespace std;int main() 
{int n,q;cin >> n >> q;vector<int> arr(n+1,0);for(int i = 1;i <= n;i++) cin >> arr[i];vector<long long> dp(n+1,0);for(int i = 1;i <= n ; i++) dp[i] = dp[i-1] + arr[i];while(q--){int l,r;cin >> l >> r;cout << dp[r] - dp[l-1] << endl;}return 0;
}

二、二维前缀和

1.链接

【模板】二维前缀和_牛客题霸_牛客网 (nowcoder.com)

2.描述

3.思路

该题我们采用动态规划的定式思路去分析得到前缀和的表,并且分析如何使用

4.参考代码

核心的思路就是上面的动归分析已经如何使用前缀和表格的部分,剩下的就是在实际写代码时候的一些细节

1.测试用例中包含较大的数据,因此在dp表格中存放的值类型需要使用long long

2.一般按照思路是先载入数据,然后再动归建立dp表,但由于我们这里dp表和arr都选择使用多一行一列的辅助位置去进行的初始化,这两个步骤可以放在同一个for循环里一起执行,但先后顺序不能变,一定是先载入arr的数据,再去执行dp

#include <iostream>
using namespace std;
#include<vector>int main() 
{//加载数据int n,m,q;cin >> n >> m >> q;vector<vector<int>> arr(n+1,vector<int>(m+1,0));vector<vector<long long>> dp(n+1,vector<long long>(m+1,0));//利用动态规划思路建立前缀和的表格//写代码的时候发现,两个步骤可以合并,因此放在一起执行for(int i = 1;i<=n;i++){for(int j = 1;j<=m;j++){cin >> arr[i][j];//加载数据dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + arr[i][j];//动归创建前缀和表格}}int x1,x2,y1,y2;//开始查询while(q--){cin >> x1 >> y1 >> x2 >> y2;cout << dp[x2][y2] - dp[x1-1][y2] - dp[x2][y1-1] + dp[x1-1][y1-1] << endl;}return 0;
}

三、寻找数组的中心下标

1.链接

724. 寻找数组的中心下标 - 力扣(LeetCode)

2.描述

3.思路

先建立前缀和表格,然后遍历一遍下标位置,去比对当前下标的前后两个部分的和是否相同,若是相同则说明当前下标就是目标值,直接返回,若是遍历结束后都没有找到,说明不存在,返回-1

要注意前缀表中和题目给的数组两者之间的映射关系,最好画图去分析,又或者可以建立多一个后缀表,去对应遍历

4.参考代码

class Solution {
public:int pivotIndex(vector<int>& nums) {int n = nums.size();vector<int> dp(n+1,0);for(int i = 1;i<=n;i++) dp[i] = dp[i-1] + nums[i-1];for(int i = 0;i<n;i++){if(dp[i] == dp[n] - dp[i+1]) return i;}return -1;}
};

四、除自身以外数组的乘积

1.链接

238. 除自身以外数组的乘积 - 力扣(LeetCode)

2.描述

3.思路

题目要求的数组是除开自己的其余所有数的乘积,那么可以将ret[i]分成两部分

1.nums[0] * nums[1] * nums[2] * ... * nums[i-1] (i位置的左半部分乘积)

2.nums[i+1] * nums[i+2] * nums[i+3] * ... *  nums[n-1](i位置的右半部分乘积)

因此我们可以利用前缀和的思想,去将前半部分和后半部分分别进行制表

head[i]:表示以i位置结束,从第头到该位置的乘积

tail[i]:表示从i位置开始,到最末尾的乘积

然后遍历填表即可

4.参考代码

class Solution {
public:vector<int> productExceptSelf(vector<int>& nums) {int n = nums.size();vector<int> ret(n);vector<int> head(n+1,1);//添加辅助位要注意映射关系vector<int> tail(n+2,1);//注意,这里需要先初始化tail的第一个值for(int i = 1;i<=n;i++) head[i] = head[i-1]*nums[i-1];for(int i = n;i>=1;i--) tail[i] = tail[i+1]*nums[i-1];//得到两个表格后,遍历填表即可for(int i = 0;i<n;i++) ret[i] = head[i]*tail[i+2];return ret;}
};

五、和为k的子数组

1.链接

560. 和为 K 的子数组 - 力扣(LeetCode)

2.描述

3.思路

4.参考代码

class Solution {
public:int subarraySum(vector<int>& nums, int k) {int sum = 0;map<int,int> hash;int count = 0;for(int i = 0;i<nums.size();i++){hash[sum]++;sum += nums[i];//此时sum为i位置的前缀和count += hash[sum-k];}return count;}
};

5.代码分析

六、和可被K整除的子数组

1.链接

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

2.描述

3.思路

4.参考代码

class Solution 
{
public:int subarraysDivByK(vector<int>& nums, int k) {map<int,int> hash;int sum = nums[0];int count = 0;for(int i = 0;i<nums.size();i++){hash[(sum%k+k)%k]++;sum+=nums[i];count += hash[(sum%k+k)%k];}return count;}
};

七、连续数组

1.链接

525. 连续数组 - 力扣(LeetCode)

2.描述

3.思路

改题目若是将所有的0都换成-1,则依然和上一题的思路是一样的,都是通过前缀和去转化

4.参考代码

class Solution 
{
public:int findMaxLength(vector<int>& nums) {unordered_map<int,int> hash;int ret = 0;int sum = 0;hash[0] = -1;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;}
};

八、矩阵区域和

1.链接

1314. 矩阵区域和 - 力扣(LeetCode)

2.描述

这题描述较复杂,大致意思就是,给你一个m*n的矩阵,并且给你一整数k,然后你得返回一个相同规模的矩阵,而这个矩阵内的数据要求是:

以【i,j】位置向上下左右各延伸k个单位然后围成的矩阵和,越界的部分视为0,例如:

3.思路

这题就是对二维前缀和的一个应用,对二维前缀和的表格建立和使用,需要熟练掌握分析,而不要去死记公式,得到二维前缀和表和得到使用方法后再根据这题进行分析,这里不重复分析,随便花个草图去分析即可

建表的递推公式:dp[i][j] = dp[i-1][j] + dp[i][j-1]  - dp[i-1][j-1] + mat[i][j]

使用表格的公式:dp[x2][y2] - dp[x1-1][y2] - dp[x2][y1-1] + dp[x1-1][y1-1]

分析:

这题首先是如何确定x1、y1、x2、y2的问题,画图分析可得(太简单了略)

(x1,y1)    = (i-k,y-k)      , (x2,y2)  = (i+k,y+k)  

除了找到对应的矩阵区间,我们很容易想到还需要对边界条件进行除了,i-k和j-k是有可能越界的,因此最多我们不能让它们小于(0,0)的位置,i+k和j+k同理,最大不能大于(m-1,n-1)的位置

x1 = max(0,i-k);   y1 = max(0,y-k);     x2 = min(m-1,i+k);     y2 = min(n-1,j+k);

还有一个细节就是下标的映射关系要注意,因为在初始化dp表(前缀和表)时,我们会添加一个辅助位,而题目给的数组是从0开始的,dp表则是从1开始,所以写代码时要注意映射关系即可

4.参考代码

class Solution 
{
public:vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int k) {int m = mat.size();int n = mat[0].size();vector<vector<int>> dp(m+1,vector<int>(n+1,0));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];//注意映射关系//开始用表填返回表vector<vector<int>> answer(m,vector<int>(n));for(int i = 0;i<m;i++){for(int j = 0;j<n;j++){int x1 = max(0,i-k), y1=max(0,j-k);int x2 = min(m-1,i+k), y2 = min(n-1,j+k);answer[i][j] = dp[x2+1][y2+1] - dp[x1][y2+1] - dp[x2+1][y1] + dp[x1][y1];//注意映射关系}}return answer;}
};

总结

本篇内容是关于前缀和的算法思想和应用,整理了一些经典的题目,从简单到难逐步递进,提供链接可以直接到力扣上做,也提供了描述可以直接通过看本篇文章去尝试思考解题,提供了参考思路和测试通过的代码(C++),整理学习下来后,个人认为一个是需要掌握一维和二维的表格建立和基本使用,还有相对较难的,但也有迹可循的一种用前缀和将题目转化,利用哈希表去优化效率的思想,参考五到七题,这个思路相对重要

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

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

相关文章

解密项目管理工具数据安全:防火防盗,保密有招

相关数据显示&#xff0c;2021年中国数字经济规模总量达到45.5万亿元&#xff0c;占到国内GDP总量的39.8%。数字经济已经渗入我们工作生活的方方面面&#xff0c;项目管理工具就是其中之一&#xff0c;在数据安全备受重视的今天如何保证项目管理工具的数据安全性&#xff1f;Zo…

达梦disql登录数据库显示“未连接”

问题&#xff1a;达梦数据库在使用disql登录时&#xff0c;显示“未连接”。 指定了IP和端口号还是连接异常。 [dmdbatest ~]$ disql sysdba/Dameng123 disql V8 SQL> select * from v$instances; 未连接 SQL> exit [dmdbatest ~]$ disql sysdba/Dameng123localhost:52…

C++运算符重载如何模拟数学表达式,或模拟Python sympy和numpy

在人工智能数学基础一书中&#xff0c;下面是一题Python求函数极限的例子&#xff1a; 【例2.6】使用Python编程求 lim( x → 1) (x^2 - 1 / x - 1) ————————————————————————————————————————— import sympy from sympy import oo…

医疗大数据现状及发展问题探讨

医疗大数据&#xff0c;作为近年来备受瞩目的领域&#xff0c;其发展和变化的速度之快令人瞩目。从最初的概念炒作到如今的实际应用&#xff0c;短短三年多的时间&#xff0c;我们已经见证了医疗大数据领域的巨大变革。 临床数据的公开透明&#xff0c;为医疗大数据的利用提供…

漫谈GIS和空间数据库技术

1 GIS和CAD有啥区别 地理信息系统&#xff08;GIS&#xff09;和计算机辅助设计&#xff08;CAD&#xff09;是两种不同的技术&#xff0c;它们在功能、应用和数据处理方面有着显著的区别。以下是根据搜索结果得出的GIS和CAD的主要区别&#xff1a; 1. **数据处理的侧重点不同…

金陵科技学院软件工程学院软件工程专业

感兴趣的小伙伴可以私信我哦~~ 是笔者写的各种高质量作业和实验哦~~ 感兴趣的小伙伴可以私信我哦~~ 是笔者写的各种高质量作业和实验哦~~ 感兴趣的小伙伴可以私信我哦~~ 是笔者写的各种高质量作业和实验哦~~ 感兴趣的小伙伴可以私信我哦~~ 是笔者写的各种高质量作业和实验哦…

【其他】灾害预警,科技助力:手机地震预警功能设置指导

22024年4月3日7时58分在台湾花莲县海域遭遇了一场7.3级的强烈地震&#xff0c;震源深度12公里&#xff0c;震中位于北纬23.81度&#xff0c;东经121.74度&#xff0c;距台湾岛约14公里。震中5公里范围内平均海拔约-3560米。这场突如其来的自然灾害给当地居民的生活带来了巨大的…

从永远到永远-Git中tag的使用

Git中tag的使用 1.tag的作用2.使用背景3.tag的使用1.种类2.创建标签3.查看标签3.推送标签4. 删除标签: 4.idea可视化操作1.创建标签2.推送标签 999 删除、指定commit、验证暂时不表 1.tag的作用 Tag(标签)用来记录某个特定的提交(commit)。一个 Tag 被用来标记重要的历史节点&…

物联网实战--入门篇之(八)嵌入式-空气净化器

目录 一、风扇调速 二、通讯协议 三、净化器运行逻辑 一、风扇调速 单片机是不能直接驱动电机的&#xff0c;因为主芯片的驱动电流比较小(50mA左右)&#xff0c;他们之间正常还要有个电机驱动器&#xff0c;常用的有TB6612、L298和L9110等&#xff0c;目前项目用的这个电机它…

猫头虎技术分享 || 断网了,还能ping127.0.0.1吗?

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

【数据分析面试】6.计算对话总数(SQL)

题目&#xff1a;计算对话总数 给定了名为 messenger_sends 的消息发送表格&#xff0c;找出总共有多少个唯一的对话。 注&#xff1a;在某些记录中&#xff0c;receiver_id 和 sender_id 从初始消息中互换了。这些记录应视为同一个对话。 示例&#xff1a; 输入&#xff1…

Linux进程控制 Part 1

Linux进程控制 文章目录 Linux进程控制Linux系统任务管理的方法PCB的原型 Linux查看获取进程id的方式现象解释 Linux 进程的状态首先学习查看进程状态的命令常见的几种状态僵尸进程的危害 孤儿进程&#xff1a; 进程优先级概念&#xff1a;PRI and NI查看进程优先级的命令 环境…

wordpress全站开发指南-面向开发者及深度用户(全中文实操)--php函数

php函数 wordpress会封装一部分函数&#xff0c;比如bloginfo该函数的作用是直接调用你设置的你的网站的名称 示例 This is our amazing custom theme <?php echo 22; function myfirstfunction(){ echo 33; echo "<p>Hello ,this is my first function</…

【pycharm】在debug循环时,如何快速debug到指定循环次数

【pycharm】在debug循环时&#xff0c;如何快速debug到指定循环次数 【先赞后看养成习惯】求关注收藏点赞&#x1f600; 在 PyCharm 中&#xff0c;可以使用条件断点来实现在特定循环次数后停止调试。这可以通过在断点处右键单击&#xff0c;然后选择 “Add Breakpoint” -&g…

力扣刷题部分笔记

Leetcode 力扣刷题笔记&#xff0c;记录了几个月来的题目记录&#xff0c;将会继续保持刷题~ 2024.01 1768.交替合并字符串 创建字符串不需要声明长度&#xff08;动态分配内存&#xff09;&#xff0c;push_back()可以加入某个字符&#xff0c;append()一般用于添加字符串…

MySQL基础【语句执行顺序】

一个SQL语句它的执行顺序对于我们思考题意有着很重要的关系 题意就是&#xff1a;找出哪些只逛超市不买单的人&#xff08;买单0元也算哦&#xff0c;可能是使用的是代金券吧&#xff09; 看到此题关键找出两个数据 参观过的人 和 买单的人 他们的差就是白嫖的人&#xff08;支…

包子凑数【蓝桥杯】/完全背包

包子凑数 完全背包 完全背包问题和01背包的区别就是&#xff0c;完全背包问题每一个物品能取无限次。 思路&#xff1a;当n个数的最大公约数不为1&#xff0c;即不互质时&#xff0c;有无限多个凑不出来的&#xff0c;即n个数都可以表示成kn&#xff0c;k为常数且不为1。当n个…

【美团笔试题汇总】2023-09-02-美团春秋招笔试题-三语言题解(CPP/Python/Java)

&#x1f36d; 大家好这里是KK爱Coding &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新美团近期的春秋招笔试题汇总&#xff5e; &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f…

31.2k star, 免费开源的白板绘图工具 tldraw

31.2k star, 免费开源的白板绘图工具 tldraw 分类 开源分享 项目名: tldraw -- 无限画布白板 Github 开源地址&#xff1a; https://github.com/tldraw/tldraw 在线测试地址&#xff1a; tldraw 文档地址&#xff1a; tldraw SDK tldraw 是一款开源免费的无限画布白板&…

HTML5动画设计工具 Hype 4 Pro v4.1.14中文激活版

Hype Pro是一款功能丰富、易用且灵活的HTML5动画设计工具&#xff0c;适用于设计师、开发者和创作者创建各种精美的交互式网页动画。它的强大功能和可视化编辑界面使用户能够快速而轻松地实现复杂的动画效果&#xff0c;同时支持多种输出格式和交互方式&#xff0c;满足用户对网…