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

算法工具箱之前缀和

前缀和

概念:前缀和(Prefix Sum)是一种重要的预处理技术,能够在O(1)时间内快速计算数组任意区间的和。

核心思想:对于数组nums,我们预先计算一个前缀和数组prefix,其中:

prefix[i]表示nums[0]nums[i]的和

一维前缀和:

#include<iostream> #include<vector> using namespace std; int main() { long long n,m; cin>>n>>m; vector<long long> arr1(n); vector<long long> arr2(n + 1); arr2[0] = 0; for(auto &x : arr1) { scanf("%d",&x); } for(int j = 1;j < arr2.size();j++) { arr2[j] = arr2[j-1] + arr1[j-1]; } long long l,r; for(int i = 0;i < m;i++) { cin>>l>>r; cout<<arr2[r] - arr2[l - 1]<<endl; } return 0; }

算法思路:先构建一个比原数组长度+1的前缀和数组,再将arr2[0] =0;然后⽤ arr2[i] 表⽰: [1, i] 区间内所有元素的和,那么 arr2[i - 1] ⾥⾯存的就是 i - 1 区间内所有元素的和,那么:可得递推公式:arr2[i] = arr2[i - 1] + arr1[i]。使⽤前缀和数组,「快速」求出「某⼀个区间内」所有元素的和:当询问的区间是[l, r] 时:区间内所有元素的和为:arr2[r] - arr2[l - 1]。

算法优势:

(1)查询高效:将O(n)的区间求和优化为O(1)的差值计算

(2)预处理思想:一次构建,多次使用

(3)扩展性强:可扩展到二维、多维情况

二位前缀和:

#include<iostream> #include<vector> using namespace std; int main() { int m, n, q; cin >> m >> n >> q; vector<vector<int>> arr(m, vector<int>(n)); vector<vector<long long>> arr2(m + 1, vector<long long>(n + 1)); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { cin >> arr[i][j]; } } vector<vector<int>> arr1(q, vector<int>(4)); for (int x = 0; x < q; x++) { for (int i = 0; i < 4; i++) { cin >> arr1[x][i]; } } for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { arr2[i][j] = arr2[i - 1][j] + arr2[i][j - 1] + arr[i - 1][j - 1] - arr2[i - 1][j - 1]; } } for (int i = 0; i < q; i++) { int x1 = arr1[i][0], y1 = arr1[i][1], x2 = arr1[i][2], y2 = arr1[i][3]; cout << arr2[x2][y2] - arr2[x1 - 1][y2] - arr2[x2][y1 - 1] + arr2[x1 - 1][y1 - 1] << endl; } return 0; }

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

(1)搞出来前缀和矩阵:这⾥就要⽤到⼀维数组⾥⾯的拓展知识,我们要在矩阵的最上⾯和最左边添加上⼀⾏和⼀列 0,这样我们就可以省去⾮常多的边界条件的处理。我们填写前缀和矩阵数组的时候,下标直接从 1 开始,能⼤胆使⽤ i - 1 , j - 1 位 置的值。

递归方程就是s[i][j]=s[i−1][j]+s[i][j−1]−s[i−1][j−1]+a[i][j]

= 新格子a[i][j]

红+蓝=s[i-1][j](上一行到 j 列的和)

红+绿=s[i][j-1](这一行到 j-1 列的和)

=s[i-1][j-1](上一行 j-1 列的和)

所以红+蓝+红+绿=红+蓝+绿+红(红多算了一次),因此s[i][j]=(红+蓝)+(红+绿)−红+黄。

(2)查询公式(求子矩阵和)

查询(x1,y1)(x2,y2)的和:sum=s[x2][y2]−s[x1−1][y2]−s[x2][y1−1]+s[x1−1][y1−1]

用颜色划分理解:把整个大矩形s[x2][y2]分成四个区域:

D= 我们要查询的子矩阵(x1,y1)(x2,y2),A+B+C+D=s[x2][y2],A+B=s[x1-1][y2],A+C=s[x2][y1-1],A=s[x1-1][y1-1]。

所以D=(A+B+C+D)−(A+B)−(A+C)+A即D=s[x2][y2]−s[x1−1][y2]−s[x2][y1−1]+s[x1−1][y1−1]。

后缀和:

概念:从一个元素开始,到数组末尾的所有元素之和。

具体来说,给定一个数组nums,它的后缀和数组suffixSum是另一个数组,其中每个元素suffixSum[i]的定义如下:suffixSum[i] = nums[i] + nums[i+1] + ... + nums[n-1]。这里,n是数组nums的长度。

计算后缀和的步骤:从后往前遍历。(与前缀和思想类似)

例题:

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

核心思路:

我们要寻找一个下标i,使得:左侧和 = 右侧和

所以我们发现只要前缀和和后缀和相等,那么这个中心下标就是这个i。

http://www.cnnetsun.cn/news/1773812.html

相关文章:

  • NeMo Guardrails CLI工具终极指南:从调试到部署的完整教程
  • Spring Boot 4.3 新特性:构建更智能的 Java 应用
  • 浏览器神器Tampermonkey:手把手教你安装和使用4款必备油猴脚本
  • Sequel批量插入性能终极指南:如何快速处理百万级数据
  • MovieGuide依赖注入教程:Dagger 2在Android项目中的终极指南
  • OpenClaw+Kimi-VL-A3B-Thinking成本对比:自建多模态服务vs商用API
  • OpenClaw+Kimi-VL-A3B-Thinking成本对比:自建vs云API哪种更划算
  • Embree错误处理与调试:常见问题排查与解决方案
  • 终极指南:如何为Tech-Interview-Cheat-Sheet开源项目贡献代码
  • 从“找茬”到“预防”:AI如何预测代码中的潜在Bug
  • C++实现字符串转整数(atoi)详解
  • OpenClaw安全实践:Qwen3.5-9B本地化处理敏感数据
  • Phi-4-mini-reasoning开发者指南:日志排查、健康检查与服务重启实操
  • 告别卡顿!香橙派PC刷入Ubuntu 22.04 LTS,保姆级从烧录到EMMC迁移全流程
  • Globby最佳实践:避免常见陷阱的7个技巧
  • 基于ESP32S3芯片的机器人控制器设计与实现
  • # 发散创新:基于事件驱动架构的实时日志监控系统设计与实现在现代分布式系统中,**事件驱动编程模型**正
  • OpenClaw开源贡献:为Qwen3.5-9B-AWQ-4bit编写自定义技能指南
  • RockyLinux 8.6安装与Linux核心命令掌握(2/2)
  • 1.4 编译与烧录第一个例程(Hello World + Blinky)
  • 如何快速掌握RePKG:Wallpaper Engine资源提取与转换的完整指南
  • 终极指南:如何用Reset Windows Update Tool快速修复Windows更新问题
  • python(13)客户信息管理系统
  • 揭秘.NET 9低代码编译管道:如何将Blazor + Source Generators响应式编译速度提升5.8倍?
  • C++内存管理 C++模板
  • 告别 redis-cli 敲断手!实测 gmssh Redis 管理器:一次线上 OOM 救场的极限复盘
  • ATCODER ABC C题解米
  • 可视掏耳勺是智商税吗?西圣、蜂鸟两大爆品掏耳勺对比,避坑必看
  • 分布式系统中枢:ZooKeeper 原理、选举与应用
  • 独家披露:Mojo官方未公开的插件签名验证机制(含Python extension loader源码级逆向分析)