From the looks of it, this seems like a simple enough problem to solve in linear time and space. We can simply take the product of all the elements in the given array and then, for each of the elements of the array, we can simply find
product of array except self value by dividing the product by .
Doing this for each of the elements would solve the problem. However, there's a note in the problem which says that we are not allowed to use division operation. That makes solving this problem a bit harder.
Approach 1: Left and Right product lists
It's much easier to build an intuition for solving this problem without division once you visualize how the different
products except self look like for each of the elements. So, let's take a look at an example array and the different products.
Looking at the figure about we can figure another way of computing those different product values.
Instead of dividing the product of all the numbers in the array by the number at a given index to get the corresponding product, we can make use of the product of all the numbers to the left and all the numbers to the right of the index. Multiplying these two individual products would give us the desired result as well.
For every given index, , we will make use of the product of all the numbers to the left of it and multiply it by the product of all the numbers to the right. This will give us the product of all the numbers except the one at the given index . Let's look at a formal algorithm describing this idea more concretely.
- Initialize two empty arrays,
Rwhere for a given index
L[i]would contain the product of all the numbers to the left of
R[i]would contain the product of all the numbers to the right of
- We would need two different loops to fill in values for the two arrays. For the array
L, would be
1since there are no elements to the left of the first element. For the rest of the elements, we simply use . Remember that
L[i]represents product of all the elements to the left of element at index i.
- For the other array, we do the same thing but in reverse i.e. we start with the initial value of
1in where is the number of elements in the array, and keep updating
R[i]in reverse. Essentially, . Remember that
R[i]represents product of all the elements to the right of element at index i.
- Once we have the two arrays set up properly, we simply iterate over the input array one element at a time, and for each element at index
i, we find the
product except selfas .
Let's go over a simple run of the algorithm that clearly depicts the construction of the two intermediate arrays and finally the answer array.
For the given array , the
R arrays would finally be:
- Time complexity : where represents the number of elements in the input array. We use one iteration to construct the array , one to construct the array and one last to construct the array using and .
- Space complexity : used up by the two intermediate arrays that we constructed to keep track of product of elements to the left and right.
Approach 2: O(1) space approach
Although the above solution is good enough to solve the problem since we are not using division anymore, there's a follow-up component as well which asks us to solve this using constant space. Understandably so, the output array does not count towards the space complexity. This approach is essentially an extension of the approach above. Basically, we will be using the output array as one of
R and we will be constructing the other one on the fly. Let's look at the algorithm based on this idea.
- Initialize the empty
answerarray where for a given index
answer[i]would contain the product of all the numbers to the left of
- We construct the
answerarray the same way we constructed the
Larray in the previous approach. These two algorithms are exactly the same except that we are trying to save up on space.
- The only change in this approach is that we don't explicitly build the
Rarray from before. Instead, we simply use a variable to keep track of the running product of elements to the right and we keep updating the
answerarray by doing . For a given index
answer[i]contains the product of all the elements to the left and
Rwould contain product of all the elements to the right. We then update
- Time complexity : where represents the number of elements in the input array. We use one iteration to construct the array , one to update the array .
- Space complexity : since don't use any additional array for our computations. The problem statement mentions that using the array doesn't add to the space complexity.
Analysis written by: @sachinmalhotra1993.