
上篇我们介绍了前缀和在一维情况和二维情况下的两大基本模板,本篇将结合具体题目分析讲解,深化我们对于前缀和算法的理解运用。
在此之前,我们先来理解什么是中心下标:即左侧所有元素相加之和等于右侧所有元素相加之和。 题目具体要求如下:
暴力解法(会超时):
class Solution {
public:
int pivotIndex(vector<int>& nums) {
int n=nums.size();
vector<int> sums1(n);//前缀和数组
vector<int> sums2(n);//后缀和数组
//处理前缀和数组
for(int i=1;i<nums.size();i++)
{
sums1[i]=sums1[i-1]+nums[i-1];
}
//处理后缀和数组
for(int i=nums.size()-2;i>=0;i--)
{
sums2[i]=sums2[i+1]+nums[i+1];
}
//匹配比较
for(int i=0;i<n;i++)
{
if(sums1[i]==sums2[i])
{
return i;
}
}
return -1;
}
};暴力解法: 创建一个数组,之后直接遍历,每一个元素都在原数组的基础上累乘求解,在数据量较大时一定会超时。
前缀和:
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int n=nums.size();
vector<int> dp1(n);//前缀乘积数组
vector<int> dp2(n);//后缀乘积数组
vector<int> ret(n);//返回数组
dp1[0]=dp2[n-1]=1;//注意初始化为1
//处理前缀数组
for(int i=1;i<n;i++)
{
dp1[i]=dp1[i-1]*nums[i-1];
}
//处理后缀数组
for(int i=n-2;i>=0;i--)
{
dp2[i]=dp2[i+1]*nums[i+1];
}
//插入返回值
for(int i=0;i<n;i++)
{
int temp=dp1[i]*dp2[i];
ret[i]=temp;
}
return ret;
}
};题目要求统计并返回数组中和为k的子数组的个数。

设i为数组中的任意位置,sums[i]表示[0,i]的数组元素和。 则数组中和为k的子数组,即代表[x,i]内的和为k,[0,x]内的和为sums[i]-k。 因此,问题就转化为有多少个[0,x]的前缀和为sums[i]-k.具体步骤如下:
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
unordered_map<int,int> hash;//记录前缀和及其出现的次数
int sum=0,ret=0;
hash[0]=1;
for(int i=0;i<nums.size();i++)
{
sum+=nums[i];
if(hash.count(sum-k))//存在
{
ret+=hash[sum-k];
}//更新个数
hash[sum]++;//更新哈希表
}
return ret;
}
};本篇关于前缀法的介绍就暂告段落啦,希望能对大家的学习产生帮助,欢迎各位佬前来支持斧正!!!