结果先存左侧前缀积,再乘右侧后缀积,O(n) 时间 O(1) 额外空间。
OJ: leetcodecn
题目 ID: product-of-array-except-self
难度:普及+/提高
标签:数组前缀和cpppython
日期: 2026-07-28 22:05
题意
返回数组 answer,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。不能用除法,O(n) 时间。
思路
最简单想到的是 O(n²) 暴力或先算总积再除以自身(但题目禁止除法且零元素会导致除零)。优化:第一次遍历存左侧前缀积到答案数组,第二次遍历从右侧乘上后缀积。
代码
cpp
/**
* Author by Rainboy
*/
// main.cpp:左侧前缀积 * 右侧后缀积,O(n) O(1) extra。
#include <bits/stdc++.h>
using namespace std;
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;
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<int> a(n);
for (int &x : a)
cin >> x;
auto v = Solution().productExceptSelf(a);
for (int x : v)
cout << x << ' ';
return 0;
}python
#!/usr/bin/env python3
from typing import List
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
n = len(nums)
ans = [1] * n
left = 1
for i in range(n):
ans[i] = left
left *= nums[i]
right = 1
for i in range(n - 1, -1, -1):
ans[i] *= right
right *= nums[i]
return ans
def main() -> None:
n = int(input())
nums = list(map(int, input().split()))
print(*Solution().productExceptSelf(nums))
if __name__ == "__main__":
main()复杂度
- 时间复杂度:O(n),两次遍历。
- 空间复杂度:O(1) 不计答案数组。
总结
"左侧前缀 + 右侧后缀"是避免除法的经典技巧,不需要特殊处理零元素。