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.