[Algorithm][前缀和][模板 一维前缀和][模板 二维前缀和][寻找数组中心下标][除自身以外数组的乘积] + 前缀和原理 + 前缀和模板

news/2024/9/23 11:15:17/

目录


0.原理讲解

  • 前缀和快速求出数组中某一个连续区间的和

  • 一维前缀和步骤:

    1. 预处理出来一个前缀和数组

      • dp[i]表示:[1, i]区间内所有元素的和
      • 状态方程转移dp[i] = dp[i - 1] + arr[i]
        请添加图片描述
    2. 使用前缀和数组

      • [l, r] -> dp[r] - dp[l - 1]
        请添加图片描述
  • 二维前缀和步骤:

    1. 预处理出来一个前缀和数组

      • dp[i][j]表示:从[1, 1]位置到[i, j]位置,这段区间里面所有元素的和
      • 状态方程转移dp[i][j] = dp[i - 1][j] + dp[i][j - 1] + arr[i][j] - dp[i - 1][j - 1]
        请添加图片描述
    2. 使用前缀和数组

      • [ x 1 , y 1 ] − [ x 2 , y 2 ] [x_1, y_1] - [x_2, y_2] [x1,y1][x2,y2] -> D = d p [ x 2 ] [ y 2 ] − d p [ x 1 − 1 ] [ y 2 ] − d p [ x 2 ] [ y 1 − 1 ] + d p [ x 1 − 1 ] [ y 1 − 1 ] D = dp[x_2][y_2] - dp[x_1 - 1][y_2] - dp[x_2][y_1 - 1] + dp[x_1 - 1][y_1 -1] D=dp[x2][y2]dp[x11][y2]dp[x2][y11]+dp[x11][y11]
        请添加图片描述
  • 为什么下标要从1开始计数?

    • 为了处理边界情况
      • 倘若l == 0,那么使用前缀和数组时就会出现dp[r] - dp[-1]
      • 但此时若从1开始计数,则为dp[2] - dp[0],此时不会出现任何问题
    • arr[0] = 0是不会影响其他值的

1.[模板]一维前缀和

1.题目链接


2.模板代码实现

int main()
{int n = 0, q = 0;cin >> n >> q;vector<int> arr(n + 1);for(int i = 1; i <= n; i++){cin >> arr[i];}// 预处理出来一个前缀和数组vector<long long> dp(n + 1);for(int i = 1; i <= n; i++){dp[i] = dp[i - 1] + arr[i];}// 使用前缀和数组int l = 0, r = 0;while(q--){cin >> l >> r;cout << dp[r] - dp[l - 1] << endl;}return 0;
}

2.[模板]二维前缀和

1.题目链接


2.算法原理讲解

  • 类⽐于⼀维数组的形式,如果能处理出来从[1, 1]位置到[i, j]位置这⽚区域内所有元素的累加和,就可以在 O ( 1 ) O(1) O(1)的时间内,搞定矩阵内任意区域内所有元素的累加和

3.模板代码实现

int main()
{int n = 0, m = 0, q = 0;cin >> n >> m >> q;// 读取数据vector<vector<int>> arr(n + 1, vector<int>(m + 1));for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){cin >> arr[i][j];}}// 预处理前缀和矩阵vector<vector<long long>> dp(n + 1, vector<long long>(m + 1));for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){dp[i][j] = dp[i - 1][j] + dp[i][j - 1] + arr[i][j] - dp[i - 1][j - 1];}}// 使用预处理数组int x1 = 0, y1 = 0, x2 = 0, y2 = 0;long long ret = 0;while(q--){cin >> x1 >> y1 >> x2 >> y2;ret = dp[x2][y2] - dp[x1 - 1][y2] - dp[x2][y1 - 1] + dp[x1 - 1][y1 - 1];cout << ret << endl;;}return 0;
}

3.寻找数组的中心下标

1.题目链接

  • 寻找数组的中心下标

2.算法原理详解

  • 由本题可感受出:前缀和类型的题不要硬套模板,题目问什么,根据题目,去微调模板就可以
    • 比如[0, i - 1]中的最大值,也可以用前缀和思想
  • 从中⼼下标的定义可知,除中⼼下标的元素外,该元素左边的**「前缀和等于该元素右边的「后缀和」**
    • 因此,可以先预处理出来两个数组,⼀个表⽰前缀和,另⼀个表⽰后缀和
    • 然后,可以循环枚举可能的中⼼下标,判断每⼀个位置的「前缀和」以及 「后缀和」,如果⼆者相等,就返回当前下标
  • 前缀和数组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]
  • 细节处理
    • f[0] = 0g[n - 1] = 0
    • f -> 从左向右 / g -> 从右向左
      请添加图片描述

3.代码实现

int PivotIndex(vector<int>& nums) 
{int n = nums.size();vector<int> f(n), g(n);// 预处理前缀和数组和后缀和数组// f[i] -> [0, i - 1]区间,所有元素的和for(int i = 1; i < n; i++){f[i] = f[i - 1] + nums[i - 1];}// g[i] -> [i + 1, n - 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;
}

4.除自身以外数组的乘积

1.题目链接


2.算法原理详解

  • 前缀积数组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]
  • 细节处理
    • f[0] = 1,g[n - 1] = 1`
    • f -> 从左向右 / g -> 从右向左
      请添加图片描述

3.代码实现

vector<int> productExceptSelf(vector<int>& nums) 
{int n = nums.size();vector<int> f(n), g(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];}// 使用vector<int> ret(n);for(int i = 0; i < n; i++){ret[i] = f[i] * g[i];}return ret;
}

http://www.ppmy.cn/news/1433149.html

相关文章

C语言 字符类型

下面 我们来说字符类型 我们来看这个 保险单 金额 和 总额 都可以用数字类型 而性别则需要字符型 字符数据的存储 – ASCI码 字符类型 char 就是专为存储字符(如字母&#xff0c;标点和数字)而设计的类型。 使用单引号包含单个字符或转义字符去表示一个 char 类型的常量。 …

TPS54560BQDDARQ1功能和参数介绍及如何进行热管理

制造商:Texas Instruments 产品品种:开关稳压器 RoHS:是 安装风格:SMD/SMT 封装 :SO-PowerPad-8 输出电压:0.8 V to 58.8 V 输出电流:5 A 输出端数量:1 Output 最大输入电压:60 V 拓扑结构:Buck 最小输入电压:4.5 V 开关频率:100 kHz to 2.5 MHz 最小作业温度:- 40 C 最大作业温…

django忽略migrate

django migrate迁移时会依次执行四件事&#xff1a; 1、迁移判定&#xff0c;将你的项目中所有未迁移的变动文件进行迁移&#xff08;django会去查询django_migrations表判断你是否有新的迁移文件变动&#xff0c;若有新的迁移文件&#xff0c;则将变动加到django_migrations表…

spring boot项目怎么预防CSRF攻击

在Spring Boot项目中预防CSRF攻击通常涉及利用Spring Security框架提供的内置支持。Spring Security已经为CSRF提供了默认的防护措施&#xff0c;但根据应用的特定需求&#xff0c;可能需要进行一些配置调整或扩展。下面是一系列步骤和建议&#xff0c;用于在Spring Boot项目中…

【webrtc】m98 RoundRobinPacketQueue的优先级处理

m98 代码 PacedSender::EnqueuePackets 的调用者可能是多个地方,所以这个要加锁保护。RoundRobinPacketQueue 本身是没有锁的发现m98和新版本不同,参考:【webrtc】m114自己实现的PrioritizedPacketQueuepush和pop都是RtpPacketToSend 但是实际上,内部是封装为QueuedPacket 处…

【C++】优先队列

优先队结构的不同物理结构与常用操作算法 优先队列是一种特殊的队列,队列中的元素具有优先级,每次弹出操作会弹出优先级最高的元素。 优先队列常用的物理结构有: 1. 数组:简单但不高效,插入和删除操作需要移动大量元素,时间复杂度高。 2. 二叉堆:是一种完全二叉树,通常用数…

tomcat 配置支持 ssl 附效果图

1、修改tomcat配置文件server.xml: vim ./conf/server.xml 把配置文件&#xff1a; <Connector port"8088" Server" " protocol"HTTP/1.1"connectionTimeout"20000"redirectPort"8443" URIEncoding"UTF-8" …

常见面试算法题-打麻将

■ 题目描述 【打麻将】 给定一个列表&#xff0c;里面含所有14个元素&#xff0c;问这14个元素&#xff0c;能不能组成33332的组合&#xff0c;3格式可以表示顺子&#xff0c;或者3张相同的牌&#xff0c;2表示对子&#xff08;两张相同的牌&#xff09;类似麻将胡牌一样&am…