【LeetCode】238. 除自身以外数组的乘积

79 阅读1分钟

「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战」。

题目

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。

题目数据 保证 数组 nums 之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。

请不要使用除法,且在O(n)O(n)时间复杂度内完成此题。

示例 1

输入: nums = [1,2,3,4]
输出: [24,12,8,6]

示例 2

输入: nums = [-1,1,0,-3,3]
输出: [0,0,9,0,0]

提示

  • 2 <= nums.length <= 105
  • -30 <= nums[i] <= 30
  • 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内

**进阶:**你可以在 O(1) 的额外空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。)

题解

思路

方法一中需要额外使用 prefix 和 suffix 两个数组去计算前缀乘积和后缀乘积,其实可以利用 output 数组的空间来优化掉这两个数组。

首先从左往右计算数组的前缀乘积,与方法一相同,只不过这次用 output 数组来存储 prefix 数组中的元素。 其次从右向左遍历数组来计算后缀乘积。 后缀乘积由一个变量 suffix 来表示。 计算后缀乘积的同时,来计算 output 数组的结果。 通过上述方法节省了 prefix 和 suffix 两个数组,其中 prefix 数组变成了 output,其次我们使用一个变量 suffix 来动态地计算后缀乘积,又省去了一个数组。后缀乘积在动态计算的同时来计算 output 的最终结果。

代码

时间复杂度:O(n)

空间复杂度:O(1)

class Solution {
    public int[] productExceptSelf(int[] nums) {
        int[] output = new int[nums.length];
        output[0] = 1;
        for (int i = 1; i < nums.length; i++) {
            output[i] = output[i-1]*nums[i-1];
        }
        int suffix = 1;
        for (int i = nums.length-1; i >= 0; i--) {
            // 等价于 output[i] = prefix[i]*suffix[i];
            output[i] = output[i]* suffix;
            suffix = suffix* nums[i];
        }
        return output;
    }
}

结语

业精于勤,荒于嬉;行成于思,毁于随。