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 <= 10530 <= nums[i] <= 30- The product of any prefix or suffix of
numsis 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
iin the arraynums:
- Set
productto 1. - Iterate through each element
jin the arraynums:- If
iequalsj, skip this iteration. - Multiply
productbynums[j].
- If
- Append
productto theoutputvector.
- Return the
outputvector.
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_Productandright_Productof sizenwith all elements set to 1. - Calculate
left_Product:
- Set
left_Product[0]to 1. - For each element
ifrom 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
ifromn-2to 0, setright_Product[i]toright_Product[i+1]multiplied bynums[i+1].
- Initialize vector
ansof sizen. - For each element
ifrom 0 ton-1, setans[i]toleft_Product[i]multiplied byright_Product[i]. - Return the
ansvector.
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
outputof sizenwith all elements set to 1. - Calculate the left product:
- Set
output[0]to 1. - For each element
ifrom 1 ton-1, setoutput[i]tooutput[i-1]multiplied bynums[i-1].
- Calculate the right product:
- Initialize
rightto 1. - For each element
ifromn-1to 0, setoutput[i]tooutput[i]multiplied by right, then setrighttorightmultiplied bynums[i].
- Return the
outputvector.
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.