Product of Array Except Self(LeetCode)
Problem Statementβ
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.
Examplesβ
Example 1:
Input: nums = [1,2,3,4]
Output: [24,12,8,6]
Example 2:
Input: nums = [-1,1,0,-3,3]
Output: [0,0,9,0,0]
Constraintsβ
2 <= nums.length <= 105
30 <= nums[i] <= 30
- The product of any prefix or suffix of
nums
is guaranteed to fit in a 32-bit integer.
Solutionβ
We can solve this problem using multiple approaches. Here, I have explained all the possible solutions:
- Brute Force Approach: Using nested loops to calculate the product of elements except for the current index.
- Dynamic Programming (Tabulation): Using two arrays to store the left and right products.
- Dynamic Programming (Space Optimization): Optimizing space usage by combining the two product arrays into a single array.
Approach Brute Force (Two Nested Loops)β
Algorithmβ
- Initialize an empty vector
output
. - Iterate through each element
i
in the arraynums
:
- Set
product
to 1. - Iterate through each element
j
in the arraynums
:- If
i
equalsj
, skip this iteration. - Multiply
product
bynums[j]
.
- If
- Append
product
to theoutput
vector.
- Return the
output
vector.
Implementationβ
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int n = nums.size();
vector<int> output;
for(int i = 0; i < n; i++) {
int product = 1;
for(int j = 0; j < n; j++) {
if(i == j) continue;
product *= nums[j];
}
output.push_back(product);
}
return output;
}
};
Complexity Analysisβ
- Time complexity: O(N^2) - Two nested loops create a quadratic time complexity.
- Space complexity: O(1) - No extra space except for the output array (which doesn't count towards space complexity).
Approach 2: Dynamic Programming (Tabulation)β
Algorithmβ
- Initialize vectors
left_Product
andright_Product
of sizen
with all elements set to 1. - Calculate
left_Product
:
- Set
left_Product[0]
to 1. - For each element
i
from 1 ton-1
, setleft_Product[i]
toleft_Product[i-1]
multiplied bynums[i-1]
.
- Calculate
right_Product
:
- Set
right_Product[n-1]
to 1. - For each element
i
fromn-2
to 0, setright_Product[i]
toright_Product[i+1]
multiplied bynums[i+1]
.
- Initialize vector
ans
of sizen
. - For each element
i
from 0 ton-1
, setans[i]
toleft_Product[i]
multiplied byright_Product[i]
. - Return the
ans
vector.
Implementationβ
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int n = nums.size();
vector<int> ans(n);
vector<int> left_Product(n);
vector<int> right_Product(n);
left_Product[0] = 1;
for(int i = 1; i < n; i++) {
left_Product[i] = left_Product[i-1] * nums[i-1];
}
right_Product[n-1] = 1;
for(int i = n-2; i >= 0; i--) {
right_Product[i] = right_Product[i+1] * nums[i+1];
}
for(int i = 0; i < n; i++) {
ans[i] = left_Product[i] * right_Product[i];
}
return ans;
}
};
Complexity Analysisβ
- Time complexity: O(N) - We iterate through the array three times.
- Space complexity: O(N) - Two additional arrays (left_Product and right_Product) are used.
Approach 3: Dynamic Programming (Space Optimization)β
Algorithmβ
- Initialize a vector
output
of sizen
with all elements set to 1. - Calculate the left product:
- Set
output[0]
to 1. - For each element
i
from 1 ton-1
, setoutput[i]
tooutput[i-1]
multiplied bynums[i-1]
.
- Calculate the right product:
- Initialize
right
to 1. - For each element
i
fromn-1
to 0, setoutput[i]
tooutput[i]
multiplied by right, then setright
toright
multiplied bynums[i]
.
- Return the
output
vector.
Implementationβ
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int n = nums.size();
vector<int> output(n);
output[0] = 1;
for(int i = 1; i < n; i++) {
output[i] = output[i-1] * nums[i-1];
}
int right = 1;
for(int i = n-1; i >= 0; i--) {
output[i] *= right;
right *= nums[i];
}
return output;
}
};
Complexity Analysisβ
- Time complexity: O(N) - We iterate through the array twice.
- Space complexity: O(1) - Constant space is used, except for the output array.
Conclusionβ
By exploring various approaches to solve this problem, we can see that the brute force method, while simple, is inefficient with a time complexity of O(N^2). The dynamic programming approach with tabulation optimizes the time complexity to O(N) but uses extra space. The most optimized approach uses space-efficient dynamic programming, maintaining O(N) time complexity while reducing space complexity to O(1). This final approach is the best in terms of both time and space efficiency.