50eb507a8dee4a5dab9d1f93273ebbf3.png

【题目】:238. 除自身以外数组的乘积
方法1. 前后缀分解 + 两个数组存放前后缀的乘积

class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
// res[i] = 当前数字的左边数乘积 * 当前数字的右边数乘积
int n = nums.size();
vector<int> left(n, 1); // nums[i]左边数乘积
vector<int> right(n, 1); // nums[i]右边数乘积
for(int i = 1; i < n; ++i) {
left[i] = left[i - 1] * nums[i - 1];
}
for(int i = n - 2; i >= 0; --i) {
right[i] = right[i + 1] * nums[i + 1];
}
vector<int> res;
for(int i = 0; i < n; ++i) {
res.push_back(left[i] * right[i]);
}
return res;
}
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

这题的难点在于,不能用乘法。
所以使用前后缀分解,用两个数组分别求nums[i]所有左边数的乘积 和 nums[i]所有右边数的乘积,求结果的时候,res[i] = 当前数字的左边数乘积 * 当前数字的右边数乘积

方法2. 前后缀分解 + O(1)的空间复杂度

class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
// res[i] = 当前数字的左边数乘积 * 当前数字的右边数乘积
int n = nums.size();
vector<int> res(n, 1);
for(int i = 1; i < n; ++i) {
res[i] = nums[i - 1] * res[i - 1]; // res[i] 先存储nums[i]所有左边数的乘积
}
int right = 1; // right存储nums[i]所有右边数的乘积
for(int i = n - 2; i >= 0; --i) {
right = right * nums[i + 1];
res[i] = right * res[i];
}
return res;
}
};

先用res[i]来存放nums[i]所有左边数的乘积,再用一个常数right来存储nums[i]所有右边数的乘积,一边更新right的值,一边更新到res[i]中