> 技术文档 > “前缀和”专题篇一

“前缀和”专题篇一

目录

【模版】前缀

【模版】二维前缀和

寻找数组的中心下标

除自身以外数组的乘积


【模版】前缀和

题目

思路

这道题如果使用暴力解法,即针对每次查询,先算出前r个数的总和,然后再算出前l-1个数的总和,然后相减就得出本次查询的结果,但是这样的话,时间复杂度是O(N*Q),会超时,因此需要别的方法来解决。

下面使用“前缀和”来解决这道题,即先算出每个位置(含该位置)之前所有数的总和,使用一个数组存储起来,然后针对每次查询就可以使用O(1)的时间复杂度得到结果。

代码

#include #include using namespace std;int main() { int n,q; cin>>n>>q; vector arr(n+1); for(int i=1;i>arr[i]; vector dp(n+1); for(int i=1;i>l>>r; cout<<dp[r]-dp[l-1]<<endl; } return 0;}
【模版】二维前缀和

题目

思路

这道题如果使用暴力解法的话,即针对针对查询,算出本次查询的区域,然后再计算出该区域所有数的和,但是这种方法的时间复杂度是O(N*M*Q),是会超时的,因此需要别的方法来解决。

下面将依旧使用“前缀和”的思想来解决这道题,即预先计算出每个位置和左上角构成的矩形的值的总和,针对每次查询,就可以使用O(1)的时间复杂度计算出所查询区域的值的总和。

【1】计算好每个位置和左上角构成的矩形的值的总和

【2】计算出所查询区域的值的总和

代码

#include #include using namespace std;int main() { int n,m,q; cin>>n>>m>>q; vector<vector> arr(n+1,vector(m+1)); for(int i=1;i<=n;i++) for(int j=1;j>arr[i][j]; vector<vector> dp(n+1,vector(m+1)); for(int i=1;i<=n;i++) for(int j=1;j>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]表示当前位置之前所有元素的和,后缀和数组g[i]表示当前位置之后所有元素的和,然后遍历每个位置,看该位置的前缀和和当前位置的后缀和是否相等。

代码

class Solution {public: int pivotIndex(vector& nums) { int n=nums.size(); vector f(n); vector g(n); for(int i=1;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计算从末尾到当前位置的下一个位置的乘积,分别计算该位置之前所有元素的乘积以及该位置之后所有元素的乘积,然后遍历整个数组,计算出每个位置除自身以外数组的乘积。

代码

class Solution {public: vector productExceptSelf(vector& nums) { int n=nums.size(); vector f(n); vector g(n); f[0]=g[n-1]=1; vector ret(n); for(int i=1;i=0;i--) g[i]=g[i+1]*nums[i+1]; for(int i=0;i<n;i++) ret[i]=f[i]*g[i]; return ret; }};