>

Product of Array Except Self

"""
238. Product of Array Except Self

https://leetcode.com/problems/product-of-array-except-self

NOTES

Given the following constraint,

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

where `n` represents the number of elements in the input array, we can only
iterate through the list once (or some constant number of times (ex. 3) as we
shall see in the solution).

Examples:

  [1, 1] -> [1, 1]
  [1, 2] -> [2, 1]
  [1, 2, 3] -> [6, 3, 2]
  [1, 2, 3, 4] -> [24, 12, 8, 6]
  [1, 2, 3, 4, 5] -> [120, 60, 40, 30, 24]

Scratch:

    i →

  j  [1, 2, 3, 4, 5] -> 120
  ↓  [1, 1, 3, 4, 5] ->  60
     [1, 2, 1, 4, 5] ->  40
     [1, 2, 3, 1, 5] ->  30
     [1, 2, 3, 4, 1] ->  24

     <- 120 ---------> L(j+1),i+1 / i,j * i+1,j
     <---- 60 -------> L(j+1),i+1 / i,j * i+1,j
     <------ 40 -----> Find the product to the left and right (L and R)
     <-------- 30 ---> R(j-1),i-1 / i,j * i-1,j
     <---------- 24 -> R(j-1),i-1 / i,j * i-1,j

     <- 120 ---------> 0 product(nums) / i * i-1
     <---- 60 -------> 1 prev / i * i-1
     <------ 40 -----> 2 prev / i * i-1
     <-------- 30 ---> 3 prev / i * i-1
     <---------- 24 -> 4 prev / i * i-1

  I was *close* on this one in that I reasoned correctly that the original
  array needed to be segmented into left and right parts, but failed to realize
  that I could not use the division operation ('/').

  The correct solution involves initializing two empty arrays, L and R where
  for a given index i, L[i] would contain the product of all the numbers to the
  left of i and R[i] would contain the product of all the numbers to the right
  of i. Using L and R, the product of index i can be easily calculated as:

    L[i] * R[i]
"""

from typing import List


class Solution:
    def productExceptSelf(self, nums: List[int]) -> List[int]:
        length = len(nums)
        L, R, res = [0] * length, [0] * length, [0] * length

        # L[i] is the product of all the elements to the left of i.
        #
        #   L[i] = L[i−1] ∗ nums[i−1]
        #
        # NOTE: For i = 0, there are no elements to the left of i, therefore
        # L[0] = 1.
        L[0] = 1
        for i in range(1, length):
            L[i] = L[i - 1] * nums[i - 1]

        # R[i] is the product of all the elements to the right of i.
        #
        #   R[i] = R[i+1] ∗ nums[i+1]
        #
        # NOTE: For i = length-1, there are no elements to the right of i,
        # therefore R[length -1] = 1.
        R[length - 1] = 1
        for i in reversed(range(length - 1)):
            R[i] = R[i + 1] * nums[i + 1]

        # Construct answer array.
        for i in range(length):
            res[i] = L[i] * R[i]
        return res

grind.rip

From Grind Hell, with Love