题目描述
给定一个数组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]。不能使用除法。(注意:规定B[0] = A[1] * A[2] * … * A[n-1],B[n-1] = A[0] * A[1] * … * A[n-2];)
对于A长度为1的情况,B无意义,故而无法构建,因此该情况不会存在。
示例1
输入
[1,2,3,4,5]
返回值
[120,60,40,30,24]
思路
思路1:最开始想的就是将所有数字乘起来,再除以对应位置的数字。但是规定不能用除法,并且假如有0就很难实现了
思路2:暴力计算
class Solution {
public:
vector<int> multiply(const vector<int>& A) {
vector<int> ret;
const int s=A.size();
for (int i=0;i<s;i++)
{
int temp=1;
for (int j=0;j<s;j++)
{
if (i==j)
continue;
else
temp*=A[j];
}
ret.push_back(temp);
}
return ret;
}
};
时间复杂度O(n^2)
时间复杂度这么高的原因就是在后面的运算中一直从头开始乘,我们可以用一个方式将之前的结果保存起来。
思路2:
先将指定位置的左边都乘起来
a | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
b左 | 1 | 1 | 2 | 6 | 24 | 120 |
这样就得到了每个位置左半部分的乘积(位置0没有左边,直接设置为1就行了)即:
b[i]=b[i-1]*a[i-1]
再从右到左乘好右半部分:
a | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
b左 | 1 | 1 | 2 | 6 | 24 | 120 |
b | 1* 2* 3* 4* 5*6 | 1* 3* 4* 5*6 | 2* 4* 5*6 | 6* 5*6 | 24*120 | 120 |
这时候需要从左到右维持一个变量存储右边的值,这个变量初始化为最右边的数,循环从倒数第2个开始。
实现:
class Solution {
public:
vector<int> multiply(const vector<int>& A) {
vector<int> ret(A.size(),1);
int len=A.size();
for (int i=1;i<len;i++)//第一轮循环左边都乘好放进数组中
{
ret[i]*=ret[i-1]*A[i-1];
}
int temp=1;
for (int i=len-2;i>=0;i--)//第二轮循环从右边倒数第二个开始往左边循环(因为最后一个是没有右边的)
{
temp*=A[i+1];//维持一个右边乘积变量
ret[i]*=temp;//这里相当于就是左边乘右边了
}
return ret;
}
};