238 - 除自身以外数组的乘积 - python + Java

249 阅读2分钟

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

示例:

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

提示:题目数据保证数组之中任意元素的全部前缀元素和后缀(甚至是整个数组)的乘积都在 32 位整数范围内。

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


如果不考虑时间复杂度,暴力法可以简单的求解

class Solution:
    def productExceptSelf(self, nums: List[int]) -> List[int]:
        if not nums: return []
        
        res = []
        for i in range(len(nums)):
            others = nums[:i] + nums[i + 1:]
            ans = 1
            for n in others:
                ans *= n
            res.append(ans)
            
        return res

正确的方法是构建前缀乘积数组L和后缀乘积数组R,最终的结果是两个数组对应索引乘积成果组成的数组。两个数组的构建和元素相乘都是O(N)的线性时间复杂度,因此,整体的时间复杂度为O(N)。由于需要辅助数组的使用,因此空间复杂度为O(N)

详细的思路看官方题解就好啦,这里就不再细写,毕竟我第一次做这个题并不能想到这种做法-_-!

class Solution:
    def productExceptSelf(self, nums: List[int]) -> List[int]:
        
        length = len(nums)
        L, R = [1] * length, [1] * length
        res = []
        for i in range(1, length):
            L[i] = nums[i - 1] * L[i - 1]

        for i in range(length - 2, -1, -1):
            R[i] =  nums[i + 1]* R[i + 1]       

        for i, j in zip(L, R):
            res.append(i * j)

        return res

2020 - 7 - 19 更新Java AC Code,如下所示:

/**
 * @Author dyliang
 * @Date 2020/7/19 22:12
 * @Version 1.0
 */
public class ProductExceptSelf {

    public static void main(String[] args) {
        int[] nums = {1, 2, 3, 4};
        int[] res = productExceptSelf(nums);
        System.out.println(Arrays.toString(res)); // [24, 12, 8, 6]
    }

    public static int[] productExceptSelf(int[] nums) {
        if (nums.length == 0 || nums.length == 1){
            return nums;
        }

        int len = nums.length;
        // 创建前缀数组和后缀数组,并初始化
        int[] L = new int[len];
        int[] R = new int[len];
        L[0] = 1;
        R[len - 1] = 1;

        for (int i = 1; i < len; i++) {
            L[i] = nums[i - 1] * L[i - 1];
        }

        for(int i = len - 2; i >= 0; i--){
            R[i] = nums[i + 1] * R[i + 1];
        }

        for (int i = 0; i < len; i++) {
            L[i] = L[i] * R[i];
        }
		// 这里直接复用了L,更好的选择是全程只使用L
		// 计算后缀数组的结果后,直接和前缀数组中对应的值相乘,然后更新保存到前缀数组
        return L;
    }
}