题目
给定一个数组 A [ 0 , 1 , . . . , n − 1 ] A[0,1,...,n-1] A[0,1,...,n−1],请构建一个数组 B [ 0 , 1 , . . . , n − 1 ] B[0,1,...,n-1] B[0,1,...,n−1],其中 B B B中的元素 B [ i ] = A [ 0 ] ∗ A [ 1 ] ∗ . . . ∗ A [ i − 1 ] ∗ A [ i + 1 ] ∗ . . . ∗ A [ n − 1 ] B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1] B[i]=A[0]∗A[1]∗...∗A[i−1]∗A[i+1]∗...∗A[n−1]。不能使用除法。
思路
- 思路一
- 创建一个二维数组,记录每个连续区间的乘积值。
- 求B的某个元素时,就把两个区间的值乘起来。
- 时间复杂度 O ( n 2 ) O(n^2) O(n2),空间复杂度 O ( n 2 ) O(n^2) O(n2)。
- 思路二
- 正反遍历两遍。正向遍历, B B B的每一项先记录前向的乘积。反向遍历一遍,再把反向的乘积乘给 B B B中对应的元素。
- 时间复杂度O(n),没有使用额外的空间。
代码一
class Solution {
public:
vector<int> multiply(const vector<int>& A) {
if ( A.size() <= 1 ) return {};
int size = A.size();
vector<int> B(size);
vector<vector<int> > memo( size, vector<int>(size, 0) );
for ( int i = 0; i < size; ++i ) {
for ( int j = i; j < size; ++j ) {
if ( i == j ) memo[i][j] = A[i];
else {
memo[i][j] = memo[i][j-1] * A[j];
}
}
}
B[0] = memo[1][size-1];
B[size-1] = memo[0][size-2];
for ( int i = 1; i < size - 1; ++i ) {
B[i] = memo[0][i-1] * memo[i+1][size-1];
}
return B;
}
};
代码二
class Solution {
public:
vector<int> multiply(const vector<int>& A) {
int size = A.size();
vector<int> B( size, 1 );
for ( int i = 1; i < size; ++i ) {
B[i] = A[i-1] * B[i-1];
}
int temp = 1;
for ( int i = size - 2; i >= 0; --i ) {
temp *= A[i+1];
B[i] *= temp;
}
return B;
}
};