返回
除自身外的数组乘积,化繁为简的解法
前端
2023-11-29 04:59:41
在算法领域,我们经常会遇到一些看似复杂但又暗藏简便之道的难题。今天,我们将探讨一个经典问题:除自身外的数组乘积 。
问题定义
给定一个长度为 n
的整数数组 nums
(其中 n > 1
),求输出数组 output
,其中 output[i]
等于 nums
中除 nums[i]
之外的其余各元素的乘积。
例如,对于数组 [1, 2, 3, 4]
,output
为 [12, 6, 4, 3]
。
朴素解法
最直接的解法是逐个计算每个元素的乘积。时间复杂度为 O(n^2)
,空间复杂度为 O(n)
。
def product_except_self_brute(nums):
output = [1] * len(nums)
for i in range(len(nums)):
for j in range(len(nums)):
if i != j:
output[i] *= nums[j]
return output
利用前缀和后缀乘积
一种更有效的方法是利用前缀乘积和后缀乘积。
- 前缀乘积:对于元素
nums[i]
,其前缀乘积为[nums[0], nums[1], ..., nums[i-1]]
的乘积。 - 后缀乘积:对于元素
nums[i]
,其后缀乘积为[nums[i+1], nums[i+2], ..., nums[n-1]]
的乘积。
利用这些乘积,我们可以通过以下公式计算 output[i]
:
output[i] = (前缀乘积[i-1] * 后缀乘积[i+1]) / nums[i]
算法步骤:
- 初始化前缀乘积和后缀乘积数组。
- 遍历数组,计算每个元素的前缀乘积。
- 从后往前遍历数组,计算每个元素的后缀乘积。
- 根据公式计算
output[i]
。
代码实现:
def product_except_self_prefix_suffix(nums):
prefix = [1] * len(nums)
suffix = [1] * len(nums)
output = [1] * len(nums)
# 计算前缀乘积
for i in range(1, len(nums)):
prefix[i] = prefix[i-1] * nums[i-1]
# 计算后缀乘积
for i in range(len(nums)-2, -1, -1):
suffix[i] = suffix[i+1] * nums[i+1]
# 计算输出
for i in range(len(nums)):
output[i] = prefix[i-1] * suffix[i+1]
return output
优化空间复杂度
上述算法的空间复杂度为 O(n)
,我们可以进一步优化为 O(1)
。
算法步骤:
- 初始化变量
prefix
为 1,表示前缀乘积。 - 遍历数组,计算每个元素
nums[i]
的前缀乘积,并将其存储在prefix
中。 - 初始化变量
suffix
为 1,表示后缀乘积。 - 从后往前遍历数组,计算每个元素
nums[i]
的后缀乘积,并将其存储在suffix
中。 - 根据公式计算
output[i]
。
代码实现:
def product_except_self_optimized(nums):
output = [1] * len(nums)
prefix = 1
# 计算前缀乘积
for i in range(len(nums)):
output[i] = prefix
prefix *= nums[i]
# 计算后缀乘积
suffix = 1
for i in range(len(nums)-1, -1, -1):
output[i] *= suffix
suffix *= nums[i]
return output
总结
我们介绍了三种计算除自身外的数组乘积的方法:朴素解法、利用前缀和后缀乘积的方法,以及优化空间复杂度的优化方法。通过不断优化算法,我们实现了算法效率和空间消耗的平衡。