赞
踩
目录
对于一个给定的数列A,他的前缀和数中 S 中 S[ i ] 表示从第一个元素到第 i 个元素的总和。
如下图:绿色区域的和就是前缀和数组中的 S [ 6 ]。
这里我们需要注意的是:前6个数的和为什么是S【6】呢?数组第6个数下标不应该是5吗?
是的,我们在下表面推导公式会讲到这个问题。
前缀和数组的每一项是可以通过原序列以递推的方式推出来的,递推公式就是:S[ i ] = S[ i - 1 ] + A[ i ]。S[ i - 1 ] 表示前 i - 1 个元素的和,在这基础上加上 A[ i ],就得到了前 i 个元素的和 S [ i ]。
当我们要求的是序列 A 的前 n 个数之和时,如果我们是从下标为 0 的位置开始存储前缀和数组,此公式:sum = S[ r ] - S[ l - 1 ] 显然就无法使用了,为了是这个公式适用于所有情况,我们将从下标为 1 的位置开始存储前缀和,并且将下标为 0 的位置初始化为 0。
【模板】前缀和_牛客题霸_牛客网 (nowcoder.com)
题目描述:
算法思路:
- #include <iostream>
- #include<vector>
- using namespace std;
-
- int main()
- {
- int n,q;
- cin>>n>>q;
- vector<int> arr(n+1,0);
- for(int i=1;i<=n;i++) cin>>arr[i];
- vector<long long> dp(n+1,0);
- for(int i=1;i<=n;i++) dp[i]=arr[i]+dp[i-1];
- int l,r;
- while(q--)
- {
- cin>>l>>r;
- cout<<dp[r]-dp[l-1]<<endl;
- }
- return 0;
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
题目描述:
算法思路:
- 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]=nums[i-1]+f[i-1];
- //后缀和
- for(int i=n-2;i>=0;i--)
- g[i]=nums[i+1]+g[i+1];
-
- for(int i=0;i<n;i++)
- {
- if(g[i]==f[i])
- return i;
- }
- return -1;
- }
- };
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
238. 除自身以外数组的乘积 - 力扣(LeetCode)
题目描述:
算法思路:
- class Solution {
- public:
- vector<int> productExceptSelf(vector<int>& nums)
- {
- int n=nums.size();
- vector<int> g(n),f(n);
- //前缀积
- f[0]=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> arr(n);
- for(int i=0;i<n;i++)
- {
- arr[i]=g[i]*f[i];
- }
- return arr;
- }
- };
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
题目描述:
算法思路:
代码实现:
- class Solution {
- public:
- int subarraySum(vector<int>& nums, int k)
- {
- unordered_map<int,int> hash;
- int sum=0,ret=0;
- hash[0]=1;
- for(auto x:nums)
- {
- sum+=x;
- if(hash.count(sum-k))
- {
- ret+=hash[sum-k];
- }
- hash[sum]++;
- }
- return ret;
- }
- };
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
974. 和可被 K 整除的子数组 - 力扣(LeetCode)
题目描述:
算法思路:
- class Solution {
- public:
- int subarraysDivByK(vector<int>& nums, int k)
- {
- unordered_map<int,int> hash; //第一个int存余数,第二个存个数
- int sum=0,ret=0;
- hash[0%k]=1;
- for(auto x:nums)
- {
- sum+=x;
- int r=(sum%k+k)%k;
- if(hash.count(r)) ret+=hash[r];
- hash[r]++;
- }
- return ret;
- }
- };
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
题目描述:
例如:对与 x = 4,y = 3 这么一组输入,就是将原矩阵序列中蓝色区域的元素相加,得到的结果便是前缀和矩阵S中 S[ 4 ][ 3 ] 的值。
例如上图:我们要求蓝色矩阵中所有元素的和。
现在就差最后一步了,怎么求出前缀和矩阵中的每一个值嘞??同理利用递推关系求就阔以啦。
S[ i ][ j ] = S[ i - 1 ][ j ] + S[ i ][ j - 1 ] - S[ i - 1][ j - 1 ] + a[ i ][ j ]
五、二维前缀和OJ题
【模板】二维前缀和_牛客题霸_牛客网 (nowcoder.com)
题目描述:
算法思路:
图解展示(图中presum[3][4]除了包括绿色部分,还包括其它重叠的部分,其它几项也一样,另外presum[1][1]被多减了一次,所以最后要加一次):
代码实现:
- #include <iostream>
- #include<vector>
- using namespace std;
-
- int main()
- {
- int n,m,q;
- cin>>n>>m>>q;
- vector<vector<long long>> arr(n+1,vector<long long>(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,x2,y1,y2;
- 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;
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
题目描述
算法思路:
代码实现:
- 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] - dp[i - 1][j - 1] + mat[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;
- }
- };
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。