前缀和一维模版:
现在要求我们找到数组里面任意一个下标的前面所有的元素(并包括这个下标的元素)的和;
我们给出一个暴力的思路,就是他给一个下标,然后我们进行遍历到该下标的位置;并进行统计和;
这样是不是太慢了;我们的前缀和就是用于解决一整块数组求和的问题;思路就是我们前面所有的元素已经求和好了,我们直接加上该下标的数组的元素就是我们要求的数;当然我们也没有说一定是从前往后求,所以我们可以用这个来求后缀和以及部分特殊要求的整块的求和问题;
根据前面的分析,我们知道了我们要有一个数组来进行存储,我们这个元素前面一个元素到下标为0元素的和;
公式:f[0]=0, f[n]=f[n-1]+arry[n-1];
724. 寻找数组的中心下标
题目解析:
我们要找到一个元素以它为分界的左右数组的和相等;
算法原理:
我们进行暴力查找:就是一个元素一个元素来进行枚举他前面的元素的和,以及他后面元素的和然后我们再进行比较二者是否相等,如果相等,那我们就进行返回;
我们在这个思路上可以进行优化,就是因为我们的前缀和就是解决一个数组连续的问题;
我们可以定义一个数组 f用他来进行存储我们前缀和的结果;f[i]表示我们的[0,i-1]的元素的和;因为我们还需要一下子找到后缀和;那我们用前缀和的思想可以搞一个,后缀和;数组g;g[i]表示[i+1,n-1];
那我们就可以写出来下面的代码了;
细节处理: 如果在最左边我们的前缀和为0;如果在最右边我们的后缀和为0;所以我们直接从最左边和最右边的下一个元素开始填入我们的数组;
class Solution {
public:
int pivotIndex(vector<int>& nums) {
int n=nums.size();
vector<int> f(n),g(n);
//vector默认给0,这样帮我们处理边界的两个元素,
for(int i=1;i<n;i++) f[i]=f[i-1]+nums[i-1];
for(int i=nums.size()-2;i>=0;i--) g[i]=g[i+1]+nums[i+1];
//进行结果查找,一旦出现左边等于右边就进行返回;
int i=0;
while(i<nums.size()) {
if(f[i]==g[i]) return i;
i++;
}
return -1;
}
};
238. 除自身以外数组的乘积
题目解析:
就是将我们当前的元素除去,数组里面其他元素乘积填入目标数组的我们当前元素下标的位置;
算法原理:
根据去我们前面的思想:我们可以进行前缀积以及后缀积的进行存储;然后我们返回的数组每一个位置就是这两个相同位置的这两个数组的元素的乘积;
细节处理:我们下标在最左边和最右边的元素,因为我们后面的乘积会用这个数,所以为了不影响后面的元素的结果,我们就统一的赋值为1;且从第二个位置开始
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int n=nums.size();
vector<int> f(n),g(n);
//前缀积
f[0]=1;
int i=1;
while(i<n){
f[i]=f[i-1]*nums[i-1];
i++;
}
//后缀积
g[n-1]=1;
i=n-2;
while(i>=0) {
g[i]=g[i+1]*nums[i+1];
i--;
}
//结果
vector<int> ans(n);
i=0;
while(i<n){
ans[i]=f[i]*g[i];
i++;
}
return ans;
}
};