题目描述:
给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B 中的元素 B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]。不能使用除法。
示例:
输入: [1,2,3,4,5]
输出: [120,60,40,30,24]
提示:
所有元素乘积之和不会溢出 32 位整数
a.length <= 100000
题目分析:
根据题目描述,函数名是constructArr,函数输入是vector& a,返回值应当是新的数组 vector ret。
数组a中的元素对应A[i],返回值数组ret中元素对应题目中的B[i],则有
B[i] = A[0]×A[1]×…×A[i-1] × A[i+1]×…×A[n-1]
我们可以把右边连乘拆分为两部分,前半部分是A[0]×A[1]×…×A[i-1],后半部分是A[i+1]×…×A[n-1]。显然B[i]等于A[i]左边所有的元素值乘积乘以A[i]右边的所有元素乘积 。
分析到这里,我们的解法就是,遍历两遍原数组,第一次正着遍历,保存A[i]左边所有的元素值乘积到
B[i]中,即ret[i]中,然后再反着遍历一遍,将A[i]右边的所有元素乘积与第一遍历时的值ret[i]相乘。
需要注意的是,相乘的时候要错位。
代码:
class Solution {
public:
vector<int> constructArr(vector<int>& a) {
int n = a.size();
vector<int> ret(n, 1);
/*
从左往右遍历累乘,结果保存在数组 retret 中,此时 ret[i]表示,A[i] 左边所有元素的乘积
然后从右往左遍历累乘,获取A[i]右边所有元素的乘积
两边遍历之后得到的 ret,就是最终结果
*/
int left = 1;
for (int i = 0; i < n; i ++)
{
ret[i] = left;
left = left * a[i];
}
int right = 1;
for (int i = n-1; i >= 0; i--)
{
ret[i] *= right;
right *= a[i];
}
return ret;
}
};