剑指 Offer(第2版)面试题 66:构建乘积数组
剑指 Offer(第2版)面试题 66:构建乘积数组
题目来源:86. 构建乘积数组
解法1:暴力
双重循环求乘积。
代码:
class Solution
{
public:
vector<int> multiply(const vector<int> &A)
{
if (A.empty())
return {};
int n = A.size();
vector<int> B;
for (int i = 0; i < n; i++)
{
int mult = 1;
for (int j = 0; j < n; j++)
if (j != i)
mult *= A[j];
B.push_back(mult);
}
return B;
}
};
复杂度分析:
时间复杂度:O(n2),其中 n 是数组 A 的长度。
空间复杂度:O(1)。
解法2:前后缀分解
代码:
class Solution
{
public:
vector<int> multiply(const vector<int> &A)
{
if (A.empty())
return {};
int n = A.size();
vector<int> prev(n + 1, 0), suffix(n + 1, 0);
prev[0] = 1;
for (int i = 1; i <= n; i++)
prev[i] = prev[i - 1] * A[i - 1];
suffix[n] = 1;
for (int i = n - 1; i >= 0; i--)
suffix[i] = suffix[i + 1] * A[i];
vector<int> B(n, 0);
for (int i = 0; i < n; i++)
B[i] = prev[i] * suffix[i + 1];
return B;
}
};
复杂度分析:
时间复杂度:O(n),其中 n 是数组 A 的长度。
空间复杂度:O(n),其中 n 是数组 A 的长度。
空间优化:除了输出的数组之外,只使用常数空间。
class Solution
{
public:
vector<int> multiply(const vector<int> &A)
{
if (A.empty())
return {};
int n = A.size();
vector<int> B(n + 1, 0);
B[n] = 1;
for (int i = n - 1; i >= 0; i--)
B[i] = B[i + 1] * A[i];
int preSum = 1;
for (int i = 0; i < n; i++)
{
B[i] = preSum * B[i + 1];
preSum *= A[i];
}
B.pop_back();
return B;
}
};
复杂度分析:
时间复杂度:O(n),其中 n 是数组 A 的长度。
空间复杂度:O(1)。