notes/OJ notes/pages/Leetcode Product-of-Array-Except-Self.md
2022-09-05 14:55:17 +08:00

179 lines
3.5 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Leetcode Product-of-Array-Except-Self
2022-09-05 14:27
> ##### Algorithms:
>
> #algorithm #prefix_sum
>
> ##### Data structures:
>
> #DS
>
> ##### Difficulty:
>
> #coding_problem #difficulty-medium
>
> ##### Additional tags:
>
> #leetcode #CS_list_need_understanding
>
> ##### Revisions:
>
> N/A
##### 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;
}
};
```