目录
一、前缀和的定义
二、一维前缀和
三、一维前缀和OJ题
3.1、前缀和
3.2、寻找数组中心下标
3.3、除自身以外数组的乘积
3.4、和为K的数组
3.5、和可被K整除的子数组
3.6、连续数组
四、二位前缀和
4.1、二维前缀和
4.2、矩阵区域和
对于一个给定的数列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
#include
using namespace std;
int main()
{
int n,q;
cin>>n>>q;
vector arr(n+1,0);
for(int i=1;i<=n;i++) cin>>arr[i];
vector 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<
724. 寻找数组的中心下标 - 力扣(LeetCode)
题目描述:
class Solution {
public:
int pivotIndex(vector& nums)
{
int n=nums.size();
vector f(n),g(n);
//前缀和
for(int i=1;i=0;i--)
g[i]=nums[i+1]+g[i+1];
for(int i=0;i
238. 除自身以外数组的乘积 - 力扣(LeetCode)
题目描述:
算法思路:
class Solution {
public:
vector productExceptSelf(vector& nums)
{
int n=nums.size();
vector g(n),f(n);
//前缀积
f[0]=g[n-1]=1;
for(int i=1;i=0;i--)
g[i]=g[i+1]*nums[i+1];
vector arr(n);
for(int i=0;i
560. 和为 K 的子数组 - 力扣(LeetCode)
题目描述:
算法思路:
代码实现:
class Solution {
public:
int subarraySum(vector& nums, int k)
{
unordered_map 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;
}
};
974. 和可被 K 整除的子数组 - 力扣(LeetCode)
题目描述:
算法思路:
class Solution {
public:
int subarraysDivByK(vector& nums, int k)
{
unordered_map 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;
}
};
525. 连续数组 - 力扣(LeetCode)
题目描述:
class Solution {
public:
int findMaxLength(vector& nums)
{
unordered_map hash;
hash[0]=-1;
int sum=0,ret=0;
for(int i=0;i
例如:对与 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
#include
using namespace std;
int main()
{
int n,m,q;
cin>>n>>m>>q;
vector> arr(n+1,vector(m+1));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>arr[i][j];
}
}
vector> dp(n+1,vector(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<
1314. 矩阵区域和 - 力扣(LeetCode)
题目描述
算法思路:
代码实现:
class Solution {
public:
vector> matrixBlockSum(vector>& mat, int k)
{
int m=mat.size(),n=mat[0].size();
vector> dp(m+1,vector(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> ret(m,vector(n));
for(int i=0;i