返回

除自身以外数组的乘积:简洁高效的算法

闲谈

引言

LeetCode 238:除自身以外数组的乘积是一个中等难度的算法问题,要求我们计算一个数组中每个元素的乘积,但不能包含元素本身。解决这一问题需要一个巧妙的算法,既能满足要求,又具有较高的效率。

思路

该算法的关键思想在于将数组的乘积拆分成两个部分:每个元素左边的乘积和右边的乘积。

具体来说,我们首先初始化两个数组:leftrightleft 数组存储每个元素左边所有元素的乘积,right 数组存储每个元素右边所有元素的乘积。

然后,我们从左到右遍历数组,计算 left 数组的每个元素。对于第一个元素,其左边没有元素,因此 left[0] = 1。对于其他元素,left[i] 可以通过 left[i - 1] * nums[i - 1] 计算得出,其中 nums[i - 1] 是第 i-1 个元素。

接着,我们从右到左遍历数组,计算 right 数组的每个元素。与 left 数组类似,对于最后一个元素,其右边没有元素,因此 right[n - 1] = 1。对于其他元素,right[i] 可以通过 right[i + 1] * nums[i + 1] 计算得出,其中 nums[i + 1] 是第 i+1 个元素。

最后,我们遍历数组,对于每个元素,其乘积可以简单地通过 left[i] * right[i] 计算得出。

示例

考虑数组 [1, 2, 3, 4]

  1. 计算 left 数组:

    • left[0] = 1
    • left[1] = 1 * 1 = 1
    • left[2] = 1 * 1 * 2 = 2
    • left[3] = 2 * 1 * 2 = 4
  2. 计算 right 数组:

    • right[3] = 1
    • right[2] = 1 * 4 = 4
    • right[1] = 4 * 3 = 12
    • right[0] = 12 * 2 = 24
  3. 计算乘积数组:

    • result[0] = left[0] * right[0] = 1 * 24 = 24
    • result[1] = left[1] * right[1] = 1 * 12 = 12
    • result[2] = left[2] * right[2] = 2 * 4 = 8
    • result[3] = left[3] * right[3] = 4 * 1 = 4

因此,给定数组 [1, 2, 3, 4],其乘积数组为 [24, 12, 8, 4]

复杂度分析

该算法的时间复杂度为 O(n),其中 n 是数组的长度。这是因为我们遍历了数组三次,每次遍历都花费 O(n) 的时间。

该算法的空间复杂度为 O(n),这是因为我们创建了两个额外的数组 leftright,每个数组的大小都为 n。

结论

除自身以外数组的乘积问题是一个经典的算法问题,需要一个巧妙的解决方案。本文中提出的算法简洁高效,易于理解和实现。它使用分治的思想将数组的乘积拆分成两个部分,从而大幅降低了算法的复杂度。