238. Product of Array Except Self
Description of Problem
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 <= 105-30 <= nums[i] <= 30- The product of any prefix or suffix of
numsis guaranteed to fit in a 32-bit integer.
Follow up: Can you solve the problem in O(1) extra Auxiliary Space? (The output array does not count as extra space for Auxiliary Space analysis.)
Solution
Tags: Prefix Sum
Explanation
Without consideration of division, we can express the answer by the following equations \[ f(x_i) = X_{0..i} \cdot X_{(i+1)..n} \text{ where } X_{i..j} = \prod_{k=i}^{j-1} x_k \text{ and } x_k \text{ is element in the array with index k}\]
By observation, \(X_{0..i}\) is the product of prefixes of \(x_i\) and \(X_{(i+1)..n}\) is the product of suffixes of \(x_i\).
For Prefixes: \[ \begin{matrix} \left [ x_0, x_1, ... ,x_{n-2} ,x_{n-1} \right ] & \longrightarrow & \left [ 1, x_0, ... ,x_{n-3} ,x_{n-2} \right ] \\ & \longrightarrow & \left [ 1, x_0, ... ,\prod_{k=0}^{n-3} x_k, \prod_{k=0}^{n-2} x_k \right ] \\ & \longrightarrow & \left [ 1, X_{0..1}, ... ,X_{0..n-2}, X_{0..n-1} \right ] \end{matrix} \]
For Suffixes: \[ \begin{matrix} \left [ x_0, x_1, ... ,x_{n-2} ,x_{n-1} \right ] & \longrightarrow & \left [ x_1, x_2, ... ,x_{n-1} ,1 \right ] \\ & \longrightarrow & \left [ \prod_{k=1}^{n-1} x_k, \prod_{k=2}^{n-1} x_k, ... ,\prod_{k=n-1}^{n-1} x_k, 1 \right ] \\ & \longrightarrow & \left [ X_{1..n}, X_{2..n}, ... , X_{n-1..n}, 1 \right ] \end{matrix} \]
And combine the prefixes and suffixes into single result.
Code (Rust)
impl Solution {
pub fn product_except_self(nums: Vec<i32>) -> Vec<i32> {
let n = nums.len();
let mut result = vec![1; n];
let (mut left_state, mut right_state) = (1, 1);
for i in 0..n {
result[i] *= left_state;
left_state *= nums[i];
result[n - i - 1] *= right_state;
right_state *= nums[n - i - 1];
}
return result;
}
}
Complexity
- n is number of elements in the array
Time complexity:
- \(\Theta(n)\)
Auxiliary Space:
- \(O(1)\)