238. 除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。
题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。
请 不要使用除法,且在 O(n) 时间复杂度内完成此题
这个问题要求不使用除法,并且要在 O(n) 时间内完成。我们可以通过 前缀积 和 后缀积 的方法来解决。
思路分析
对于每个位置 i,我们想要的结果是:
answer[i] = (nums[0] * nums[1] * ... * nums[i-1]) * (nums[i+1] * ... * nums[n-1])
= 前缀乘积 * 后缀乘积
方法:
- 先从左到右计算每个位置左侧所有元素的乘积(前缀积)
- 再从右到左计算每个位置右侧所有元素的乘积(后缀积),同时与左侧乘积相乘得到最终结果
为了 O(1) 额外空间(除了输出数组),我们可以:
- 先用输出数组存储前缀积
- 再用一个变量从右到左累乘后缀积,同时更新输出数组
算法步骤
- 初始化
answer[0] = 1 - 从左到右遍历:
answer[i] = answer[i-1] * nums[i-1](计算前缀积) - 初始化
suffix = 1 - 从右到左遍历:
answer[i] *= suffix且suffix *= nums[i](乘以后缀积)
代码实现
/**
* @param {number[]} nums
* @return {number[]}
*/
var productExceptSelf = function(nums) {
const n = nums.length;
const answer = new Array(n);
// 第一步:计算每个位置左侧所有元素的乘积
answer[0] = 1;
for (let i = 1; i < n; i++) {
answer[i] = answer[i - 1] * nums[i - 1];
}
// 第二步:乘上右侧所有元素的乘积
let suffix = 1;
for (let i = n - 1; i >= 0; i--) {
answer[i] *= suffix;
suffix *= nums[i];
}
return answer;
};
示例演示
例子:nums = [1,2,3,4]
第一步(前缀积):
answer[0] = 1
answer[1] = answer[0] * nums[0] = 1 * 1 = 1
answer[2] = answer[1] * nums[1] = 1 * 2 = 2
answer[3] = answer[2] * nums[2] = 2 * 3 = 6
此时 answer = [1, 1, 2, 6]
第二步(乘后缀积):
i=3: answer[3] *= 1 = 6*1=6, suffix=1*4=4
i=2: answer[2] *= 4 = 2*4=8, suffix=4*3=12
i=1: answer[1] *= 12 = 1*12=12, suffix=12*2=24
i=0: answer[0] *= 24 = 1*24=24, suffix=24*1=24
最终 answer = [24, 12, 8, 6]
验证:
- 24 = 234
- 12 = 134
- 8 = 124
- 6 = 123
复杂度分析
- 时间复杂度:O(n) - 两次遍历
- 空间复杂度:O(1) - 除了输出数组外只用了常数空间
这种方法高效且满足题目要求,是最优解法。
挣钱养家

浙公网安备 33010602011771号