- # Leetcode Product-of-Array-Except-Self

  2022-09-05 14:27

  > ##### Algorithms:
  >
  > #algorithm #prefix_sum
  >
  > ##### Data structures:
  >
  > #DS
  >
  > ##### Difficulty:
  >
  > #coding_problems #difficulty_medium
  >
  > ##### Additional tags:
  >
  > #leetcode #CS_list_need_understanding
  >
  > ##### Revisions:
  >
  > [[Mar 28th, 2023]] 14:09

##### Links:

- [Link to problem](https://leetcode.com/problems/product-of-array-except-self/)
- [Solution with explanation](<https://leetcode.com/problems/product-of-array-except-self/discuss/1597994/C%2B%2BPython-4-Simple-Solutions-w-Explanation-or-Prefix-and-Suffix-product-O(1)-space-approach>)

  ***

### 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.

#### 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.

### Thoughts

> [!summary]
> This is a variation of #prefix_sum

I thought of using prefix product, a variation of
prefix_sum, which perfectly fits the requirement.

#### First iteration:

keep two arrays: the suffix product and the prefix product
of the `nums` array.

Then, `ans = prefix[i] * suffix[i]`

#### Second iteration:

> It's like rolling snowball, the suffix sum variable
> gets reused

We can use only one output array:

write the prefix to the `ans` array, and update it from
end using suffix sum variable.

This achieves the `O(1) space except output` requirement.

#### Third iteration:

Since the multiplying process is independent, and can be
reversed, We can do that in one loop.

`1 * A * B == 1 * B * A`

If we initialize the ans array as one, we can do that in one
loop.

### Solution

Third version:

```cpp
class Solution {
public:
vector<int> productExceptSelf(vector<int> &nums) {
// Optimized one-pass prefix sum & suffix sum
int size = nums.size();

vector<int> ans(size, 1);

int prefix = 1, suffix = 1;

for (int i = 0; i < size; i++) {
  ans[i] *= prefix;
  prefix *= nums[i];

  ans[size - i - 1] *= suffix;
  suffix *= nums[size - i - 1];
}

return ans;
}
};
```

Second version:

```cpp
class Solution {
public:
vector<int> productExceptSelf(vector<int> &nums) {
// Optimized prefix sum & suffix sum
int size = nums.size();
vector<int> ans(size);

ans[0] = 1;
for (int i = 1; i < size; i++) {
  ans[i] = ans[i - 1] * nums[i - 1];
}

int suffix = 1;

for (int i = size - 1; i >= 0; i--) {
  ans[i] = ans[i] * suffix;
  suffix = suffix * nums[i];
}

return ans;
}
};
```

First iteration:

```cpp
class Solution {
public:
vector<int> productExceptSelf(vector<int> &nums) {
// method 1: prefix sum & suffix sum
vector<int> ans;
vector<int> suffix;
int size = nums.size();
ans.resize(size);
suffix.resize(size);

ans[0] = 1;
for (int i = 1; i < size; i++) {
  ans[i] = ans[i - 1] * nums[i - 1];
}

suffix[size - 1] = 1;
for (int i = size - 2; i >= 0; i--) {
  suffix[i] = suffix[i + 1] * nums[i + 1];
}

for (int i = 0; i < size; i++) {
  ans[i] = ans[i] * suffix[i];
}

return ans;
}
};
```
