除自身以外数组的乘积算法详解
今天的题目是力扣面试经典150题中的数组的中等难度题:除自身以外数组的乘积。
问题描述
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。
题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。
请不要使用除法,且在 O(n) 时间复杂度内完成此题。
-
示例 1:
-
输入:
nums = [1,2,3,4] -
输出:
[24,12,8,6] -
解释: 对于每个位置 i,output[i] 是 nums 中除 nums[i] 以外所有元素的乘积。
-
-
示例 2:
-
输入:
nums = [-1,1,0,-3,3] -
输出:
[0,0,9,0,0] -
解释: 对于每个位置 i,output[i] 是 nums 中除 nums[i] 以外所有元素的乘积。
-
题目分析
先看题目要求,给定数组,输出一个数组,并且这个数组的每个元素的值,是给定数组除当前位置外所有元素的乘积。
我们再看示例,也很明显:
- 24 = 2x3x4
- 12 = 1x3x4
- 8 = 1x2x4
- 6 = 1x2x3
- 0 = 1x0x-3x3
- 0 = -1x0x-1x3
- 9 = -1x1x-3x3
- 0 = -1x1x0x3
- 0 = -1x1x0x-3
那么,对题目要求我们已经明确了,再看题目其他信息:请不要使用除法,且在 O(n) 时间复杂度内完成此题。
正常情况下,这种求除自身元素外乘积的题目,直接所有元素相乘再除自身就能得到答案(求和,差,商类似),但是题目要求我们不能用除法,所以这个解法直接排除。
在 O(n) 时间复杂度内完成此题,这句话就明确了,我们解答题目,最多只能一层for循环,这样才能保证时间复杂度在O(n),但是题目没有要求空间复杂度,所以我们考虑用多个数组来实现解题。
解题思路
题目要求新数组元素的值是除自身外的所有元素的乘积,是不是可以理解为 元素左边的所有元素的乘积与元素右边所有元素的乘积再相乘呢?另外,由于首个位置的元素和最后位置的元素缺失一边的元素乘积,为了不影响结果,我们可以设定缺失的那边值为1。
由此,我们针对示例的分析可以修改如下:
- 24 = 1(假定的左边乘积) x (2x3x4)(右边的乘积)
- 12 = 1(左边的乘积)x(3x4)(右边的乘积)
- 8 = (1x2)(左边的乘积)x4(右边的乘积)
- 6 = (1x2x3)(左边的乘积)x1(假定的右边乘积)
另外在分析的时候,我们已经考虑了用多个数组实现解题,因为多个数组分多次循环,不改变时间复杂度为O(n),只是影响空间复杂度。
所以我们可以直接设定两个数组,一个数组计算元素左边的乘积,一个元素计算右边的乘积,最后相乘,即可得到答案。
当然,实际计算的时候,我们在计算第二个数组的乘积的时候,将第一个数组的乘积相乘即可。
实际算法代码
以下是使用上述思路的 Java 实现: