算法笔记(三)——前缀和算法
算法笔记(三)——前缀和算法
文章目录
- 算法笔记(三)——前缀和算法
- 一维前缀和
- 二维前缀和
- 寻找数组的中心下标
- 除自身以外数组的乘积
- 和为 K 的子数组
- 和可被 K 整除的子数组
- 连续数组
- 矩阵区域和
前缀和算法是一种用空间换时间的算法,他常常用于解决某些题目或者作为某些高级算法的组成部分
一维前缀和
题目链接:DP34 【模板】前缀和

思路
- 通过数组
arr存储输入的n个整数,数组dp存储数组arr的前缀和 - 使用循环读取数组元素,并计算前缀和
dp - 进行
q次查询,每次查询给定一个区间[l, r]。查询结果为dp[r] - dp[l-1],表示数组在区间[l, r]的和
C++代码
#include<iostream>
using namespace std;int main()
{int n, q;cin >> n >> q;long long arr[100001]={0}, dp[100001]={0};for(int i = 1; i <= n;++i){cin >> arr[i];dp[i] = arr[i] + dp[i-1];}while(q--){int l, r;cin >> l >> r;cout << dp[r] - dp[l-1] << endl;}return 0;
}
二维前缀和
题目:DP35 【模板】二维前缀和

思路
初始化前缀和

- 构造前缀和数组
dp[i][j],其含义是从(1,1)到(i,j)区域的面积; D区域也是dp[i][j]存储的值,其面积也等于A+B+C+D- 初始化前缀和
dp[i][j] = (A+B)+(A+C)+D - A = dp[i-1][j]+dp[i][j-1]+arr[i][j]-dp[i-1][j-1]
使用前缀和计算
D = A+B+C+D-(A+B)-(A+C)+AD = dp[i][j]-dp[i][j-1]-dp[i-1][j]+dp[i-1][j-1]
C++代码
#include <iostream>
using namespace std;int arr[1100][1100];
long long dp[1100][1100];
int n, m, q, x1, x2, y1, y2;int main()
{cin >> n >> m >> q;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] + arr[i][j] - dp[i-1][j-1]; }}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;
}
寻找数组的中心下标
题目:寻找数组的中心下标

思路
- 初始化
f表示前缀和,g表示后缀和 f[i]表示[0,i-1]所有元素的和,f[i] = f[i-1] + nums[i-1];g[i]表示[i+1,n-1]所有元素的和,g[i] = g[i+1] + nums[i+1];- 遍历数组
nums,找到一个索引,使得f[i](左侧元素的和)等于l[i](右侧元素的和)
C++代码
class Solution {
public:int pivotIndex(vector<int>& nums) {int n = nums.size();vector<int> f(n), g(n);for (int i = 1; i < n; i++)f[i] = f[i - 1] + nums[i - 1];for (int i = n - 2; i >= 0; i--)g[i] = g[i + 1] + nums[i + 1];for (int i = 0; i < n; i++)if (f[i] == g[i])return i;return -1;}
};
除自身以外数组的乘积
题目:除自身以外数组的乘积

思路
- 初始化
f表示前缀积,g表示后缀积 f[i]表示[0,i-1]所有元素的积,f[i] = f[i - 1] * nums[i - 1];g[i]表示[i+1,n-1]所有元素的积,g[i] = g[i+1] * nums[i+1];- 遍历数组
nums,计算res[i]的值
C++代码
class Solution
{
public:vector<int> productExceptSelf(vector<int>& nums) {int n = nums.size();vector<int> f(n + 1);vector<int> g(n + 1);vector<int> res(n);f[0] = 1, g[n - 1] = 1; for(int i = 1; i < n; i++)f[i] = f[i - 1] * nums[i - 1];for(int i = n - 2; i >= 0; i--)g[i] = g[i + 1] * nums[i + 1];for(int i = 0; i < n; i++)res[i] = f[i] * g[i];return res; }
};
和为 K 的子数组
题目:和为 K 的子数组

思路
将问题转化为寻找和为k的子数组,
而不是直接在数组中寻找和为k的连续元素,
这样就可以使问题在一次遍历中解决
具体来说就是:对于每个前缀和,都检查是否存在一个早先的前缀和,使得它们的差等于k。如果存在,就找到了一个和为k的子数组
- 初始化一个哈希表
hash,其中hash[0]表示和为 0 的子数组的个数,初始化为 1 - 两个变量
sum和ret,其中 sum 表示当前累积的和,ret 表示满足条件的子数组的个数 - 遍历数组
nums,累积和并更新哈希表
对于每个元素x,更新sum += x
检查是否存在之前的累积和sum - k在哈希表中,如果存在,则累加hash[sum - k]到ret。更新哈希表中的当前累积和sum的计数
C++代码
class Solution
{
public:int subarraySum(vector<int>& nums, int k) {// K:前缀和// V:前缀和出现的次数unordered_map<int, int> hash;int sum = 0, ans = 0;// 初始化时为空区间,则前缀和为0,出现的次数为1hash[0] = 1;for(int num : nums) {sum += num; ans += hash[sum - k]; // 要么为0,要么为sum - k出现的次数hash[sum]++;}return ans;}
};
和可被 K 整除的子数组
题目:和可被 K 整除的子数组

补充
- 同余定理
若(a-b) % p = k......0,则a % p = b % p - C++、Java中
负数%正数等于负数
修正a % p + p
为了a>0或a<0统一后(a % p + p) % p
思路
和上题基本相同,转化为在[0, i - 1]中,找到有多少个前缀和的余数等于(sum % k + k) % k
- 在
for(auto x : nums)的循环中,遍历数组nums。对于每个元素x sum += x; 累加当前位置的元素,得到当前位置的前缀和。int r = (sum % k + k) % kif(hash.count(r)) ret += hash[r]; 检查之前是否存在相同的余数r,如果存在,则将哈希表中对应的次数累加到结果ret中。hash[r]++; 更新哈希表,将当前余数 r 的次数加一
C++代码
class Solution
{
public:int subarraysDivByK(vector<int>& nums, int k) {unordered_map<int, int> hash;hash[0] = 1; // 初始时,前缀和为 0 的余数的个数为 1 int sum = 0;int ret = 0;for(auto x : nums){sum += x; // 当前位置前缀和int r = (sum % k + k) % k;if(hash.count(r)) // 检查之前是否存在相同的余数 r,如果存在ret += hash[r]; hash[r]++; // 更新哈希表,将当前余数 r 的次数加一}return ret;}
};
连续数组
题目:连续数组

思路
- 将 0 看作 -1,问题就转换成在数组中,找出最长的子数组使其和为0
unordered_map<int, int> hash表示创建一个哈希表,用于存储前缀和以及对应的出现位置- 遍历数组
nums对于每个元素nums[i],如果nums[i] 是 0,则令sum += -1;如果是1,则令sum += 1。这样sum就表示当前位置的前缀和; - 判断哈希表中是否存在当前前缀和
sum。如果存在,说明从上次该前缀和出现的位置到当前位置的子数组的和为零,更新最长长度ret。 - 如果哈希表中不存在当前前缀和
sum,则将当前前缀和和对应的位置存入哈希表中
C++代码
class Solution
{
public:int findMaxLength(vector<int>& nums) {unordered_map<int,int> hash;hash[0] = -1;int ret = 0;int sum = 0;for(int i = 0; i < nums.size(); ++i){sum += (nums[i] == 1 ? 1 : -1);if(hash.count(sum)) ret = max(ret, i - hash[sum]);else hash[sum]=i;}return ret;}
};
矩阵区域和
题目:矩阵区域和

思路
二维前缀和问题,但是需要处理好边界问题
int m=mat.size(), n=mat[0].size()获取矩阵的行数和列数vector<vector<int>> dp(m+1,vector<int>(n+1))创建二维前缀和数组dpdp[i][j]表示矩阵左上角(0,0)到(i-1,j-1)的元素和,计算前缀和数组dp- 对于每个位置
(i,j),计算块的左上角和右下角的坐标,确保不超过矩阵边界
C++代码
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));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] + mat[i - 1][j - 1] - dp[i - 1][j - 1];vector<vector<int>> ret(m,vector<int>(n));for(int i = 0; i < m; i++)for(int j = 0; j < n; j++){int x1 = max(0, i - k) + 1, y1 = max(0, j - k) + 1;int x2 = min(m - 1, i + k) + 1, y2 = min(n - 1, j + k) + 1;ret[i][j] = dp[x2][y2] - dp[x1 - 1][y2] - dp[x2][y1 - 1] + dp[x1 - 1][y1 - 1];}return ret;}
};
相关文章:
算法笔记(三)——前缀和算法
算法笔记(三)——前缀和算法 文章目录 算法笔记(三)——前缀和算法一维前缀和二维前缀和寻找数组的中心下标除自身以外数组的乘积和为 K 的子数组和可被 K 整除的子数组连续数组矩阵区域和 前缀和算法是一种用空间换时间的算法&am…...
Nginx技术深度解析与实战应用
Nginx技术深度解析与实战应用 Nginx是一款轻量级、高性能的Web服务器、反向代理服务器及电子邮件(IMAP/POP3)代理服务器,由俄罗斯的程序设计师Igor Sysoev开发。Nginx以其内存占用少、启动迅速、高并发能力强等特性,在互联网项目…...
Maven Surefire Plugin
Maven Surefire Plugin 最新版本新特性详解 Maven Surefire Plugin 是用于运行单元测试和集成测试的重要工具,支持 JUnit、TestNG 等测试框架。插件的新版本引入了许多新特性和配置选项,这些功能提升了测试执行的性能、灵活性和并发能力。在本节中&…...
八、跳跃、闪避
一、人物跳跃功能 1、动画 设置一个bool值 条件设置为true 2、逻辑 实现跳跃,一定有IsGround;判断是否为地面,进行跳跃功能 写一个跳跃和一个条约结束方法 跳跃设置为false,结束设置为true 3、代码 public void Jump() {if…...
使用辅助分类器 GAN 进行条件图像合成
Conditional Image Synthesis with Auxiliary Classifier GANs Conditional Image Synthesis with Auxiliary Classifier GANs(简称AC-GANs)是一种用于改善生成对抗网络(GANs)进行图像合成的方法。在AC-GANs中,判别器…...
C#中的static关键字:静态成员与单例模式的实现
在C#中,static 关键字是一个非常重要的概念,它用于声明静态成员,这些成员属于类本身,而不是类的任何特定实例。使用 static 关键字可以定义静态类、静态字段、静态属性、静态方法等。此外,理解静态成员也对于实现如单例…...
【优选算法】(第八篇)
目录 串联所有单词的⼦串(hard) 题目解析 讲解算法原理 编写代码 最⼩覆盖⼦串(hard) 题目解析 讲解算法原理 编写代码 串联所有单词的⼦串(hard) 题目解析 1.题目链接:. - 力扣&#…...
告别PPT熬夜!Kimi+AIPPT一键生成PPT,效率upup!
Kimi AiPPT 一键生成PPT 还在为做PPT熬夜加班吗?还在为PPT排版抓狂吗?现在,有一个好消息要告诉所有“打工人”!Kimi和AIPPT强强联手,推出了一键生成PPT功能,让你告别PPT制作的痛苦! 以前做…...
大语言模型在构建UNSPSC 分类数据中的应用
UNSPSC 是联合国标准产品和服务代码。UNSPSC由联合国开发计划署(UNDP)和Dun & Bradstreet公司(D & B)于1998年联合制定,自2003年以来一直由GS1 US管理。GS1 US 将在 2024 年底前将 UNSPSC 的管理权移交给 UNDP…...
C++初阶:STL详解(十)——priority_queue的介绍,使用以及模拟实现
✨✨小新课堂开课了,欢迎欢迎~✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:C:由浅入深篇 小新的主页:编程版小新-CSDN博客 一.priority_queue的介绍 优先级队列被实现…...
Qt | Linux+QFileSystemWatcher文件夹和文件监视(例如监视U盘挂载目录)
点击上方"蓝字"关注我们 01、QFileSystemWatcher >>> QFileSystemWatcher 是 Qt 提供的一个类,用于监视文件和目录的变化。它允许应用程序监控一个或多个文件和目录,并在这些文件或目录内容发生变化时收到通知。这使得 Qt 应用程序能够动态响应文件系统的…...
【Linux进程间通信】Linux匿名管道详解:构建进程间通信的隐形桥梁
📝个人主页🌹:Eternity._ ⏩收录专栏⏪:Linux “ 登神长阶 ” 🌹🌹期待您的关注 🌹🌹 ❀Linux进程间通信 📒1. 进程间通信介绍📚2. 什么是管道📜3…...
【力扣 | SQL题 | 每日三题】力扣1148, 1327, 1211, 1174
1. 力扣1148:文章浏览1 1.1 题目: Views 表: ------------------------ | Column Name | Type | ------------------------ | article_id | int | | author_id | int | | viewer_id | int | | view_date …...
【鸿蒙开发】详解GridRowSizeOption的尺寸属性
文章目录 1. 尺寸属性的含义2. 为什么要有这几个属性3. 具体作用4. 如何使用总结 在鸿蒙(HarmonyOS)开发中,布局的灵活性和适应性对于构建高质量的应用至关重要。 GridRowSizeOption是鸿蒙开发框架提供的一个布局属性,用于定义网…...
Sping源码:三级缓存
目录 一、概念1、三级缓存的作用2、循环依赖的含义 二、代码1、代码下载2、文件功能介绍3、源码分析3.1、找到获取A对象的位置,打断点进行debug操作3.2、一步步找到在A对象中注入B对象的位置3.3、一步步找到B对象注入A对象的位置3.4、往下找到通过三级缓存解决循环依…...
latex有哪些颜色中文叫什么,Python绘制出来
latex有哪些颜色中文叫什么,Python绘制出来 为了展示xcolor包预定义的颜色及其对应的中文名称,并使用Python打印出来,我们可以先列出常见的预定义颜色名称,然后将它们翻译成中文,并最后用Python打印出来。 步骤 列出…...
C语言进程
什么是进程 什么是程序 一组可以被计算机直接识别的 有序 指令 的集合。 通俗讲:C语言编译后生成的可执行文件就是一个程序。 那么程序是静态还是动态的? 程序是可以被存储在磁盘上的,所以程序是静态的。 那什么是进程 进程是程序的执行过…...
C#基础(4)封装——成员方法
前言 我们在上一节学习了关于类的成员变量的使用,甚至也看到了相应的成员方法,我们可以将二者理解为类里面的变量和函数。 如果我这样说你肯定就能很快理解成员方法是什么作用了。 C#中设计成员方法的目的是为了将相关的功能代码组织在一起࿰…...
springbot,JWT令牌的使用。实现http请求拦截校验。
JWT 由三部分组成,用点(.)分隔 Header(头部) Payload(负载)Signature(签名) 一、原理 Jwt原理其实很简单,在后端首先要有个拦截器,他会拦截所有http请求&…...
【SQL】DDL语句
文章目录 1.SQL通用语法2.SQL的分类3.DDL3.1数据库操作3.2 表操作3.2.1 表操作--数据类型3.2.2 表操作--修改3.2.3 表操作--删除 SQL 全称 Structured Query Language,结构化查询语言。操作关系型数据库的编程语言,定义了一套操作关系型数据库统一标准 。…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门  / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...
Bean 作用域有哪些?如何答出技术深度?
导语: Spring 面试绕不开 Bean 的作用域问题,这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开,结合典型面试题及实战场景,帮你厘清重点,打破模板式回答,…...
CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
