无数个相同的常数数组怎么设置_LeetCode 题解 | 238. 除自身以外数组的乘积

ecce523d529a87e344421e63cf06aeab.png

力扣 238. 除自身以外数组的乘积 (点击查看题目)

题目描述

给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。

示例:

5df1b938a7a337867f8164d18deb9511.png

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

进阶

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

解决方案

概述

这似乎是一个简单的问题,可以在线性时间和空间内解决。可以先计算给定数组所有元素的乘积,然后对数组中的每个元素 x ,将乘积除以 x 来求得除自身值的以外的数组乘积。

然后这样的解决方法有一个问题,就是如果输入数组中出现 0,那么这个方法就失效了。而且在问题中说明了不允许使用除法运算。这增加了这个问题的难度。

方法一:左右乘积列表

我们不必将所有数字的乘积除以给定索引处的数字得到相应的答案,而是可以利用索引处左侧的所有数字乘积和右侧所有数字的乘积相乘得到答案。

对于给定索引 i,我们将使用它左边所有数字的乘积乘以右边所有数字的乘积。让我们更加具体的描述这个算法。

算法

  1. 初始化两个空数组 L 和 R。对于给定索引 i,L[i] 代表的是 i左侧所有数字的乘积,R[i] 代表的是 i 右侧所有数字的乘积。
  2. 我们需要用两个循环来填充 L 和 R 数组的值。对于数组 L,L[0]应该是 1,因为第一个元素的左边没有元素。对于其他元素:L[i]=L[i-1]*nums[i-1]。
  3. 同理,对于数组 R,R[length-1] 应为 1。length 指的是输入数组的大小。其他元素:R[i]=R[i+1]*nums[i+1]。
  4. 当 R 和 L 数组填充完成,我们只需要在输入数组上迭代,且索引 i处的值为:L[i]*R[i]。

让我们用以下图片看看算法是如何工作的:

467d90104f269b4bbb2a4e4d33529176.png
6b58b4221b90ee129039df91dd16d5c5.png
b4c52b315352821709ebe21d8e0f7bfd.png
a2f8c2bb319efcb543a907c23d191986.png
94637930c7ca04fe29da5f94521d9e37.png
aa7fa8df8f596552e1bba752c48011fd.png
ffb001868c8cab6fc6b38bd776e47b4d.png
c7912abed7cec94f682c2781820649a9.png
ed32bb88771dcc762cd72e3b0f9445e0.png
072d8fb06e64fdad4883562d31f289d4.png

Python 实现(请在电脑端查看代码)

class Solution:    def productExceptSelf(self, nums: List[int]) -> List[int]:                # The length of the input array         length = len(nums)                # The left and right arrays as described in the algorithm        L, R, answer = [0]*length, [0]*length, [0]*length                # L[i] contains the product of all the elements to the left        # Note: for the element at index '0', there are no elements to the left,        # so the L[0] would be 1        L[0] = 1        for i in range(1, length):                        # L[i - 1] already contains the product of elements to the left of 'i - 1'            # Simply multiplying it with nums[i - 1] would give the product of all             # elements to the left of index 'i'            L[i] = nums[i - 1] * L[i - 1]                # R[i] contains the product of all the elements to the right        # Note: for the element at index 'length - 1', there are no elements to the right,        # so the R[length - 1] would be 1        R[length - 1] = 1        for i in reversed(range(length - 1)):                        # R[i + 1] already contains the product of elements to the right of 'i + 1'            # Simply multiplying it with nums[i + 1] would give the product of all             # elements to the right of index 'i'            R[i] = nums[i + 1] * R[i + 1]                # Constructing the answer array        for i in range(length):            # For the first element, R[i] would be product except self            # For the last element of the array, product except self would be L[i]            # Else, multiple product of all elements to the left and to the right            answer[i] = L[i] * R[i]                return answer

Java 实现(请在电脑端查看代码)

class Solution {    public int[] productExceptSelf(int[] nums) {        // The length of the input array        int length = nums.length;        // The left and right arrays as described in the algorithm        int[] L = new int[length];        int[] R = new int[length];        // Final answer array to be returned        int[] answer = new int[length];        // L[i] contains the product of all the elements to the left        // Note: for the element at index '0', there are no elements to the left,        // so L[0] would be 1        L[0] = 1;        for (int i = 1; i < length; i++) {            // L[i - 1] already contains the product of elements to the left of 'i - 1'            // Simply multiplying it with nums[i - 1] would give the product of all            // elements to the left of index 'i'            L[i] = nums[i - 1] * L[i - 1];        }        // R[i] contains the product of all the elements to the right        // Note: for the element at index 'length - 1', there are no elements to the right,        // so the R[length - 1] would be 1        R[length - 1] = 1;        for (int i = length - 2; i >= 0; i--) {            // R[i + 1] already contains the product of elements to the right of 'i + 1'            // Simply multiplying it with nums[i + 1] would give the product of all            // elements to the right of index 'i'            R[i] = nums[i + 1] * R[i + 1];        }        // Constructing the answer array        for (int i = 0; i < length; i++) {            // For the first element, R[i] would be product except self            // For the last element of the array, product except self would be L[i]            // Else, multiple product of all elements to the left and to the right            answer[i] = L[i] * R[i];        }        return answer;    }}

复杂度分析

时间复杂度:O(N),其中 N 指的是输入数组的大小。

空间复杂度:O(N),使用了 L 和 R 数组去构造答案。

方法二:空间复杂度 O(1) 的方法

尽管上面的方法已经能够很好的解决这个问题,但是不是常数的空间复杂度。

由于输出数组不算在空间复杂度内,那么我们可以将 L 或 R 数组在用输出数组来计算,然后再动态构造另一个。让我们来看看基于这个思想的算法。

算法

  1. 初始化 answer 数组,对于给定索引 i,answer[i] 代表的是 i左侧所有数字的乘积。
  2. 构造方式与之前相同,只是我们视图节省空间。
  3. 这种方法的唯一变化就是我们没有构造 R 数组。而是用一个遍历来跟踪右边元素的乘积。并更新数组 answer[i] = answer[i] * R。然后 R 更新为 R = R* nums[i]

Python 实现(请在电脑端查看代码)

class Solution:    def productExceptSelf(self, nums: List[int]) -> List[int]:                # The length of the input array         length = len(nums)                # The answer array to be returned        answer = [0]*length                # answer[i] contains the product of all the elements to the left        # Note: for the element at index '0', there are no elements to the left,        # so the answer[0] would be 1        answer[0] = 1        for i in range(1, length):                        # answer[i - 1] already contains the product of elements to the left of 'i - 1'            # Simply multiplying it with nums[i - 1] would give the product of all             # elements to the left of index 'i'            answer[i] = nums[i - 1] * answer[i - 1]                # R contains the product of all the elements to the right        # Note: for the element at index 'length - 1', there are no elements to the right,        # so the R would be 1        R = 1;        for i in reversed(range(length)):                        # For the index 'i', R would contain the             # product of all elements to the right. We update R accordingly            answer[i] = answer[i] * R            R *= nums[i]                return answer

Java 实现(请在电脑端查看代码)

class Solution {    public int[] productExceptSelf(int[] nums) {        // The length of the input array         int length = nums.length;        // Final answer array to be returned        int[] answer = new int[length];        // answer[i] contains the product of all the elements to the left        // Note: for the element at index '0', there are no elements to the left,        // so the answer[0] would be 1        answer[0] = 1;        for (int i = 1; i < length; i++) {            // answer[i - 1] already contains the product of elements to the left of 'i - 1'            // Simply multiplying it with nums[i - 1] would give the product of all             // elements to the left of index 'i'            answer[i] = nums[i - 1] * answer[i - 1];        }        // R contains the product of all the elements to the right        // Note: for the element at index 'length - 1', there are no elements to the right,        // so the R would be 1        int R = 1;        for (int i = length - 1; i >= 0; i--) {            // For the index 'i', R would contain the             // product of all elements to the right. We update R accordingly            answer[i] = answer[i] * R;            R *= nums[i];        }        return answer;    }}

复杂度分析

时间复杂度:O(N),其中 N 指的是输入数组的大小。

空间复杂度:O(1),问题的描述中说明了输出数组不算空间复杂度。

本文作者:力扣

声明:本文归“力扣”版权所有,如需转载请联系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值