238. Product of Array Except Self
Problem Description
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.
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 <= 10⁵
-30 <= nums[i] <= 30
- The product of any prefix or suffix of
nums
is guaranteed to fit in a 32-bit integer
Follow up:
Can you solve the problem in O(1) extra space complexity? (The output array does not count as extra space for space complexity analysis.)
Solution
Python Solution
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
n = len(nums)
answer = [1] * n
# Calculate prefix products
prefix = 1
for i in range(n):
answer[i] = prefix
prefix *= nums[i]
# Calculate suffix products and combine with prefix products
suffix = 1
for i in range(n - 1, -1, -1):
answer[i] *= suffix
suffix *= nums[i]
return answer
Time Complexity: O(n)
We make two passes through the array.
Space Complexity: O(1)
Only uses a constant amount of extra space (not counting the output array).
Java Solution
class Solution {
public int[] productExceptSelf(int[] nums) {
int n = nums.length;
int[] answer = new int[n];
// Calculate prefix products
answer[0] = 1;
for (int i = 1; i < n; i++) {
answer[i] = answer[i-1] * nums[i-1];
}
// Calculate suffix products and combine with prefix products
int suffix = 1;
for (int i = n - 1; i >= 0; i--) {
answer[i] *= suffix;
suffix *= nums[i];
}
return answer;
}
}
Time Complexity: O(n)
We make two passes through the array.
Space Complexity: O(1)
Only uses a constant amount of extra space (not counting the output array).
C++ Solution
class Solution {
public:
vector productExceptSelf(vector& nums) {
int n = nums.size();
vector answer(n);
// Calculate prefix products
answer[0] = 1;
for (int i = 1; i < n; i++) {
answer[i] = answer[i-1] * nums[i-1];
}
// Calculate suffix products and combine with prefix products
int suffix = 1;
for (int i = n - 1; i >= 0; i--) {
answer[i] *= suffix;
suffix *= nums[i];
}
return answer;
}
};
Time Complexity: O(n)
We make two passes through the array.
Space Complexity: O(1)
Only uses a constant amount of extra space (not counting the output array).
JavaScript Solution
/**
* @param {number[]} nums
* @return {number[]}
*/
var productExceptSelf = function(nums) {
const n = nums.length;
const answer = new Array(n);
// Calculate prefix products
answer[0] = 1;
for (let i = 1; i < n; i++) {
answer[i] = answer[i-1] * nums[i-1];
}
// Calculate suffix products and combine with prefix products
let suffix = 1;
for (let i = n - 1; i >= 0; i--) {
answer[i] *= suffix;
suffix *= nums[i];
}
return answer;
};
Time Complexity: O(n)
We make two passes through the array.
Space Complexity: O(1)
Only uses a constant amount of extra space (not counting the output array).
C# Solution
public class Solution {
public int[] ProductExceptSelf(int[] nums) {
int n = nums.Length;
int[] answer = new int[n];
// Calculate prefix products
answer[0] = 1;
for (int i = 1; i < n; i++) {
answer[i] = answer[i-1] * nums[i-1];
}
// Calculate suffix products and combine with prefix products
int suffix = 1;
for (int i = n - 1; i >= 0; i--) {
answer[i] *= suffix;
suffix *= nums[i];
}
return answer;
}
}
Time Complexity: O(n)
We make two passes through the array.
Space Complexity: O(1)
Only uses a constant amount of extra space (not counting the output array).
Approach Explanation
The solution uses a clever approach to calculate products without using division:
- Key Insight:
- For each index i, we need product of all numbers except nums[i]
- This can be broken down into prefix product × suffix product
- We can calculate these in two passes
- Steps:
- First pass: Calculate prefix products
- Second pass: Calculate suffix products and combine
- Each element gets product of all numbers before and after it
Example walkthrough for [1,2,3,4]:
- After prefix pass: [1,1,2,6]
- After suffix pass: [24,12,8,6]
- For index 2: prefix=2 (1×2), suffix=4 (4×1), result=8
Key insights:
- No division needed
- O(1) extra space (excluding output array)
- Works with zero values
- Handles negative numbers correctly