GuilinDev

Lc0238

05 August 2008

238 Product of Array Except Self

原题概述

Given an array ‘nums’ of n integers where n > 1, return an array ‘output’ such that ‘output[i]’ is equal to the product of all the elements of ‘nums’ except ‘nums[i]’.

Example:

1
2
Input:  [1,2,3,4]
Output: [24,12,8,6]

Note: Please solve it without division and in O(n).

Follow up:
Could you solve it with constant space complexity? (The output array does not count as extra space for the purpose of space complexity analysis.)

题意和分析

给一个数组,让返回一个新数组,对于每一个位置上的数是其他位置上数的乘积,并且限定了时间复杂度O(n),不让用除法。对于数组中的某个元素,如果知道该数前面所有数的乘积,也知道该数后面所有数的乘积,二者相乘就是对该数的结果;根据这一点,可以先遍历数组两遍,第一次遍历算出针对第i个元素前面所有元素的乘积,第二次遍历算出针对第i个元素后面所有元素的乘积;然后第三次遍历分别相乘即可;

可以对空间进行优化,无需单独的数组来保存乘积,而是直接累积到result中,第一次遍历,将所有i元素前面的乘积的累积存入result数组中,然后从后面开始遍历,用一个临时变量back来存储后面的乘积,初始化为1,然后每次不断累积,将back的值乘入到相对应的result数组的位置上。

代码

用数组来保存乘积

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
    public int[] productExceptSelf(int[] nums) {
        int len = nums.length;
        int[] front = new int[len], back = new int[len], result = new int[len];
        //初始化乘积为1
        front[0] = 1;
        back[len - 1] = 1;
        //计算i元素前面所有元素的乘积
        for (int i = 1; i < len; i++) {
            front[i] = front[i - 1] * nums[i - 1];
        }
        //计算i元素后面所有元素的乘积
        for (int i = len - 2; i >= 0; i--) {
            back[i] = back[i + 1] * nums[i + 1];
        }

        //二者相乘
        for (int i = 0; i < len; i++) {
            result[i] = front[i] * back[i];
        }
        return result;
    }
}

优化空间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
    public int[] productExceptSelf(int[] nums) {
        // nums = [1,2,3,4]
        int len = nums.length;
        int[] result = new int[len];
        result[0] = 1;
        
        // result: [1,0,0,0] -> [1,1,0,0] -> [1,1,2,0] -> [1,1,2,6]
        for (int i = 1; i < len; i++) {
            result[i] = result[i - 1] * nums[i - 1];
        }

        int back = 1; // 记录后缀乘积
        // result: [1,1,2,6], back 1 -> [1,1,8,6], back 4 -> [1,12,8,6], back 12 -> [1,1,2,6], back 24
        for (int i = len - 1; i >= 0; i--) {
            result[i] = back * result[i]; // 后缀乘积乘以前缀乘积
            back *= nums[i]; //更新后缀乘积
        }
        return result;
    }
}