179 lines
3.5 KiB
Markdown
179 lines
3.5 KiB
Markdown
# 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;
|
||
}
|
||
};
|
||
``` |