Post

LC 238 - Product of Array Except Self

LC 238 - Product of Array Except Self

Question

Given an integer array nums, return an array answer such that answer[i] is equal to the product of all the elements of nums except nums[i].

The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer.

You must write an algorithm that runs in O(n) time and without using the division operation.

Example 1:

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

Example 2:

1
2
Input: nums = [-1,1,0,-3,3]
Output: [0,0,9,0,0]

Constraints:

  • 2 <= nums.length <= 105
  • -30 <= nums[i] <= 30
  • The input is generated such that answer[i] is guaranteed to fit in a 32-bit integer.

Follow up: Can you solve the problem in O(1) extra space complexity? (The output array does not count as extra space for space complexity analysis.)

Question here and solution here

Solution

concept

The main idea is to use prefix sum and suffix sum and calculate the product twice: front to back and back to front. One way to reduce space complexity is to store the values directly in the answer array. Take note that in the NeetSolution, the prefix sum start (index = 0) at 1, essentially the prefix sum array starts at index = 1 so it sort of lag behind the nums. This means that the prefix sum array at index = k does not contain nums[k]. This is the same for suffix sum although this array is not explicitly computed. As a result, when we do the product of prefix and suffix, the current index’s contribution is ignored.

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
class Solution:
	"""
	my solution
	prefix and suffix
	"""
    def productExceptSelf(self, nums: List[int]) -> List[int]:
        prefix_sum = [nums[0]]
        suffix_sum = [nums[-1]]
        ans = []

        for i in range(1, len(nums)):
            prefix_sum.append(nums[i]*prefix_sum[-1])

        for j in range(len(nums) - 2, -1, -1):
            suffix_sum.append(nums[j]*suffix_sum[-1])
        suffix_sum.reverse()

        for k in range(0, len(nums)):
            if k == 0:
                ans.append(suffix_sum[1])
            elif k == len(nums) - 1:
                ans.append(prefix_sum[-2])
            else:
                ans.append(prefix_sum[k-1]*suffix_sum[k+1])

        return ans
        
class NeetSolution(object):
    def productExceptSelf(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]

        space complexity: O(1)
        time complexity: O(n)

        went through the list twice, once from left to right, and once from right to left
        from left to right: calculate product of all elements to the left of the current element -> prefix
        from right to left: calculate product of all elements to the right of the current element -> postfix, then multiply it with the prefix
        both prefix and post fix store at the same array, so the space complexity is O(1)
        """
        ans = [1] * len(nums)

        prefix = 1
        for i in range(len(nums)):
            ans[i] = prefix
            prefix = prefix * nums[i]

        postfix = 1
        for i in range(len(nums)-1, -1, -1):
            ans[i] = postfix * ans[i]
            postfix = postfix * nums[i]

        return ans
    
class NeetSolution:
    def productExceptSelf(self, nums: List[int]) -> List[int]:
        res = [1] * (len(nums))

        for i in range(1, len(nums)):
            res[i] = res[i-1] * nums[i-1]
        postfix = 1
        for i in range(len(nums) - 1, -1, -1):
            res[i] *= postfix
            postfix *= nums[i]
        return res

Complexity

time: $O(n)$
space: $O(1)$

This post is licensed under CC BY 4.0 by the author.