当前位置: 首页 > news >正文

算法笔记(三)——前缀和算法

算法笔记(三)——前缀和算法

文章目录

  • 算法笔记(三)——前缀和算法
  • 一维前缀和
  • 二维前缀和
  • 寻找数组的中心下标
  • 除自身以外数组的乘积
  • 和为 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)+A
  • D = 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
  • 两个变量 sumret,其中 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 整除的子数组

在这里插入**加粗样式**图片描述
补充

  1. 同余定理
    若(a-b) % p = k......0,则a % p = b % p
  2. 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) % k
  • if(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))创建二维前缀和数组dp
  • dp[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;}
};

相关文章:

算法笔记(三)——前缀和算法

算法笔记&#xff08;三&#xff09;——前缀和算法 文章目录 算法笔记&#xff08;三&#xff09;——前缀和算法一维前缀和二维前缀和寻找数组的中心下标除自身以外数组的乘积和为 K 的子数组和可被 K 整除的子数组连续数组矩阵区域和 前缀和算法是一种用空间换时间的算法&am…...

Nginx技术深度解析与实战应用

Nginx技术深度解析与实战应用 Nginx是一款轻量级、高性能的Web服务器、反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器&#xff0c;由俄罗斯的程序设计师Igor Sysoev开发。Nginx以其内存占用少、启动迅速、高并发能力强等特性&#xff0c;在互联网项目…...

Maven Surefire Plugin

Maven Surefire Plugin 最新版本新特性详解 Maven Surefire Plugin 是用于运行单元测试和集成测试的重要工具&#xff0c;支持 JUnit、TestNG 等测试框架。插件的新版本引入了许多新特性和配置选项&#xff0c;这些功能提升了测试执行的性能、灵活性和并发能力。在本节中&…...

八、跳跃、闪避

一、人物跳跃功能 1、动画 设置一个bool值 条件设置为true 2、逻辑 实现跳跃&#xff0c;一定有IsGround&#xff1b;判断是否为地面&#xff0c;进行跳跃功能 写一个跳跃和一个条约结束方法 跳跃设置为false&#xff0c;结束设置为true 3、代码 public void Jump() {if…...

使用辅助分类器 GAN 进行条件图像合成

Conditional Image Synthesis with Auxiliary Classifier GANs Conditional Image Synthesis with Auxiliary Classifier GANs&#xff08;简称AC-GANs&#xff09;是一种用于改善生成对抗网络&#xff08;GANs&#xff09;进行图像合成的方法。在AC-GANs中&#xff0c;判别器…...

C#中的static关键字:静态成员与单例模式的实现

在C#中&#xff0c;static 关键字是一个非常重要的概念&#xff0c;它用于声明静态成员&#xff0c;这些成员属于类本身&#xff0c;而不是类的任何特定实例。使用 static 关键字可以定义静态类、静态字段、静态属性、静态方法等。此外&#xff0c;理解静态成员也对于实现如单例…...

【优选算法】(第八篇)

目录 串联所有单词的⼦串&#xff08;hard&#xff09; 题目解析 讲解算法原理 编写代码 最⼩覆盖⼦串&#xff08;hard&#xff09; 题目解析 讲解算法原理 编写代码 串联所有单词的⼦串&#xff08;hard&#xff09; 题目解析 1.题目链接&#xff1a;. - 力扣&#…...

告别PPT熬夜!Kimi+AIPPT一键生成PPT,效率upup!

Kimi AiPPT 一键生成PPT 还在为做PPT熬夜加班吗&#xff1f;还在为PPT排版抓狂吗&#xff1f;现在&#xff0c;有一个好消息要告诉所有“打工人”&#xff01;Kimi和AIPPT强强联手&#xff0c;推出了一键生成PPT功能&#xff0c;让你告别PPT制作的痛苦&#xff01; 以前做…...

大语言模型在构建UNSPSC 分类数据中的应用

UNSPSC 是联合国标准产品和服务代码。UNSPSC由联合国开发计划署&#xff08;UNDP&#xff09;和Dun & Bradstreet公司&#xff08;D & B&#xff09;于1998年联合制定&#xff0c;自2003年以来一直由GS1 US管理。GS1 US 将在 2024 年底前将 UNSPSC 的管理权移交给 UNDP…...

C++初阶:STL详解(十)——priority_queue的介绍,使用以及模拟实现

✨✨小新课堂开课了&#xff0c;欢迎欢迎~✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C&#xff1a;由浅入深篇 小新的主页&#xff1a;编程版小新-CSDN博客 一.priority_queue的介绍 优先级队列被实现…...

Qt | Linux+QFileSystemWatcher文件夹和文件监视(例如监视U盘挂载目录)

点击上方"蓝字"关注我们 01、QFileSystemWatcher >>> QFileSystemWatcher 是 Qt 提供的一个类,用于监视文件和目录的变化。它允许应用程序监控一个或多个文件和目录,并在这些文件或目录内容发生变化时收到通知。这使得 Qt 应用程序能够动态响应文件系统的…...

【Linux进程间通信】Linux匿名管道详解:构建进程间通信的隐形桥梁

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;Linux “ 登神长阶 ” &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀Linux进程间通信 &#x1f4d2;1. 进程间通信介绍&#x1f4da;2. 什么是管道&#x1f4dc;3…...

【力扣 | SQL题 | 每日三题】力扣1148, 1327, 1211, 1174

1. 力扣1148&#xff1a;文章浏览1 1.1 题目&#xff1a; Views 表&#xff1a; ------------------------ | Column Name | Type | ------------------------ | article_id | int | | author_id | int | | viewer_id | int | | view_date …...

【鸿蒙开发】详解GridRowSizeOption的尺寸属性

文章目录 1. 尺寸属性的含义2. 为什么要有这几个属性3. 具体作用4. 如何使用总结 在鸿蒙&#xff08;HarmonyOS&#xff09;开发中&#xff0c;布局的灵活性和适应性对于构建高质量的应用至关重要。 GridRowSizeOption是鸿蒙开发框架提供的一个布局属性&#xff0c;用于定义网…...

Sping源码:三级缓存

目录 一、概念1、三级缓存的作用2、循环依赖的含义 二、代码1、代码下载2、文件功能介绍3、源码分析3.1、找到获取A对象的位置&#xff0c;打断点进行debug操作3.2、一步步找到在A对象中注入B对象的位置3.3、一步步找到B对象注入A对象的位置3.4、往下找到通过三级缓存解决循环依…...

latex有哪些颜色中文叫什么,Python绘制出来

latex有哪些颜色中文叫什么&#xff0c;Python绘制出来 为了展示xcolor包预定义的颜色及其对应的中文名称&#xff0c;并使用Python打印出来&#xff0c;我们可以先列出常见的预定义颜色名称&#xff0c;然后将它们翻译成中文&#xff0c;并最后用Python打印出来。 步骤 列出…...

C语言进程

什么是进程 什么是程序 一组可以被计算机直接识别的 有序 指令 的集合。 通俗讲&#xff1a;C语言编译后生成的可执行文件就是一个程序。 那么程序是静态还是动态的&#xff1f; 程序是可以被存储在磁盘上的&#xff0c;所以程序是静态的。 那什么是进程 进程是程序的执行过…...

C#基础(4)封装——成员方法

前言 我们在上一节学习了关于类的成员变量的使用&#xff0c;甚至也看到了相应的成员方法&#xff0c;我们可以将二者理解为类里面的变量和函数。 如果我这样说你肯定就能很快理解成员方法是什么作用了。 C#中设计成员方法的目的是为了将相关的功能代码组织在一起&#xff0…...

springbot,JWT令牌的使用。实现http请求拦截校验。

JWT 由三部分组成&#xff0c;用点&#xff08;.&#xff09;分隔 Header&#xff08;头部&#xff09; Payload&#xff08;负载&#xff09;Signature&#xff08;签名) 一、原理 Jwt原理其实很简单&#xff0c;在后端首先要有个拦截器&#xff0c;他会拦截所有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&#xff0c;结构化查询语言。操作关系型数据库的编程语言&#xff0c;定义了一套操作关系型数据库统一标准 。…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT&#xff0c;橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版&#xff1a;职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...