题目

暴力
思路:对每个位置 i,遍历整个数组,跳过 nums[i]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class SolutionBrute { public: vector<int> productExceptSelf(vector<int>& nums) { int n = nums.size(); vector<int> ans(n, 1);
for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { if (i != j) ans[i] *= nums[j]; } }
return ans; } };
|
复杂度:
- 时间:
O(n2)
- 额外空间:
O(1),不计返回数组
优化
思路:前缀积 + 后缀积
定义prefix[i]为 i 左边所有元素的乘积
定义suffix[i]为 i 右边所有元素的乘积
那么答案为answer[i] = prefix[i] * suffix[i]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class SolutionPrefixSuffix { public: vector<int> productExceptSelf(vector<int>& nums) { int n = nums.size(); vector<int> prefix(n, 1), suffix(n, 1), ans(n);
for (int i = 1; i < n; ++i) prefix[i] = prefix[i - 1] * nums[i - 1];
for (int i = n - 2; i >= 0; --i) suffix[i] = suffix[i + 1] * nums[i + 1];
for (int i = 0; i < n; ++i) ans[i] = prefix[i] * suffix[i];
return ans; } };
|
复杂度:
最优
思路:结果数组存前缀积,变量保存后缀积。不额外创建 prefix 和 suffix 数组。
第一遍:
第二遍:
- 用变量 right 保存 i 右边的乘积
- 直接乘到 ans[i]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Solution { public: vector<int> productExceptSelf(vector<int>& nums) { int n = nums.size(); vector<int> ans(n, 1);
int left = 1; for (int i = 0; i < n; ++i) { ans[i] = left; left *= nums[i]; }
int right = 1; for (int i = n - 1; i >= 0; --i) { ans[i] *= right; right *= nums[i]; }
return ans; } };
|
复杂度:
- 时间:
O(n)
- 额外空间:
O(1),返回数组不计入额外空间