Skip to content

Commit a3d4fb4

Browse files
committed
dsa
- (leetcode) product of array except self - prefix sum
1 parent 2d897f1 commit a3d4fb4

File tree

5 files changed

+130
-93
lines changed

5 files changed

+130
-93
lines changed

content/Algorithm/Prefix Sum (前缀和).md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Author Profile:
66
tags:
77
- dsa
88
Creation Date: 2023-10-08T19:28:00
9-
Last Date: 2024-05-31T14:37:50+08:00
9+
Last Date: 2024-06-01T13:20:47+08:00
1010
---
1111
## Abstract
1212
---
@@ -15,7 +15,7 @@ Last Date: 2024-05-31T14:37:50+08:00
1515

1616
- Prefix sum is an [[Array]] that has the **same length** as a **given array**
1717
- The **value at each index** is the **sum** of values from the **first element of the given array** to the **element at the current index**
18-
- Calculates the **sum of a particular range** of a **given array** efficiently by leveraging on [[Memoization]]
18+
- [[#Range Sum Query]] enables us to calculates the **sum of a particular range** of a **given array** efficiently by leveraging on [[Memoization]]
1919

2020
## Range Sum Query
2121
---
@@ -28,12 +28,12 @@ Last Date: 2024-05-31T14:37:50+08:00
2828

2929

3030
>[!tip]
31-
>$Range[0, j]$ is **same** as $P_j$. So we can just retrieve the value from the prefix sum array with index $j$, instead of using the formula stated in the diagram above, which requires us to have a placeholder at index $0$.
31+
>$Range[0, j]$ is **same** as $P_j$. So we can just retrieve the value from the **prefix sum array** with index $j$, instead of using the formula stated in the diagram above, which requires us to have a placeholder at index $0$.
3232
3333

3434

3535
## Practice Questions
3636
---
37-
- [ ] [[Product of Array Except Self]]
37+
- [ ] [[Leetcode - Product of Array Except Self]]
3838
- [ ] [[Romantic Glasses]]
3939
- [ ] [[Closest Cities]]
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
---
2+
sthNew: true
3+
Mastery Level:
4+
- 📘
5+
Time Taken: 15
6+
Space:
7+
- O(1)
8+
Time: O(n)
9+
Appears On:
10+
- Grind 75
11+
Brush: 5
12+
Difficulty:
13+
- Medium
14+
Area:
15+
- prefix_sum
16+
- dynamic_programming
17+
Reference 1: https://leetcode-solution-leetcode-pp.gitbook.io/leetcode-solution/medium/238.product-of-array-except-self
18+
Reference 2:
19+
Author:
20+
- Xinyang YU
21+
Author Profile:
22+
- https://linkedin.com/in/xinyang-yu
23+
Creation Date: 2024-01-08, 12:52
24+
Last Date: 2024-06-01T15:10:38+08:00
25+
tags:
26+
- cp
27+
draft:
28+
description: Leetcode 238. Product of Array Except Self, detailed solution with hand-crafted visual
29+
---
30+
31+
## Abstract
32+
---
33+
- [Product of Array Except Self](https://leetcode.com/problems/product-of-array-except-self/) gives us an [[Array]], and we need to produce a new array with the same length, the elements inside the new array is the product of all the elements in the given array, excluding the element at the same index
34+
- The solution must run in `O(n)`
35+
- Can't use division operation
36+
- The new array does not count as extra space for [[Algorithm Complexity Analysis#Worst Space Complexity]]
37+
- We can make use of the idea presented in [[Prefix Sum (前缀和)]], **storing** the **intermediate product** to **avoid duplicated computation**. This allows us to obtain the answer in $O(n)$ time
38+
39+
## Solution
40+
---
41+
42+
![[product_of_array_except_self.svg|600]]
43+
44+
- We can make use of the idea presented in [[Prefix Sum (前缀和)]], **storing** the **intermediate product** to **avoid duplicated computation** as shown in the diagram above. This allows us to obtain the answer in $O(n)$ time
45+
- The element at a **particular index of the new array** is the **product** of **all elements at the left side** of that particular index and **all element at the right side** of that particular index. So we have **prefix product array** that keeps track of the **product of all elements at the left side** for all indexes, and **suffix product array** that keeps track of the **product of all elements at the right side** for all indexes. Then the answer is just the product of the **intermediate product** from **prefix product array** and **suffix product array**
46+
- Below is the code implementation with Java based idea described above. From `prefix[i] = prefix[i - 1] * nums[i - 1]` and `suffix[i] = suffix[i + 1] * nums[i + 1]`, we can see we are making use of [[Dynamic Programming#Optimal Substructure (最优子结构)]] to avoid [[Dynamic Programming#Overlapping Subproblems (重复子问题)]]. We are able to use [[Dynamic Programming#Top-down DP Approach]] to create the **prefix product array** and **suffix product array**. `prefix[0] = 1` and `suffix[nums.length - 1] = 1` are the base case
47+
48+
```java
49+
class Solution {
50+
public int[] productExceptSelf(int[] nums) {
51+
int[] prefix = new int[nums.length];
52+
int[] suffix = new int[nums.length];
53+
int[] res = new int[nums.length];
54+
55+
prefix[0] = 1;
56+
suffix[nums.length - 1] = 1;
57+
58+
for (int i = 1; i < nums.length; i++) {
59+
prefix[i] = prefix[i - 1] * nums[i - 1];
60+
}
61+
62+
for (int i = nums.length - 2; i >= 0; i--) {
63+
suffix[i] = suffix[i + 1] * nums[i + 1];
64+
}
65+
66+
for (int i = 0; i < nums.length; i++) {
67+
res[i] = prefix[i] * suffix[i];
68+
}
69+
70+
return res;
71+
}
72+
}
73+
```
74+
75+
- We can further optimise the solution by replacing the **suffix product array** with **a variable** `suffix` as shown below. We are using `res` to produce the **prefix product array**, then compute the final answer array with the `suffix` variable, the **final product** at a **particular index** just needs the **suffix at that particular index**, **optimal substructure**
76+
77+
```java
78+
class Solution {
79+
public int[] productExceptSelf(int[] nums) {
80+
int[] res = new int[nums.length];
81+
res[0] = 1;
82+
83+
for (int i = 1; i < nums.length; i++) {
84+
res[i] = res[i - 1] * nums[i - 1];
85+
}
86+
87+
int suffix = 1;
88+
for (int i = nums.length - 2; i >= 0; i--) {
89+
suffix *= nums[i + 1];
90+
res[i] = res[i] * suffix;
91+
}
92+
93+
return res;
94+
}
95+
}
96+
```
97+
98+
99+
100+
## Space & Time Analysis
101+
---
102+
The analysis method we are using is [[Algorithm Complexity Analysis]]
103+
### Space - O(1)
104+
- *Ignore input size & language dependent space*
105+
- The output array isn't counted as stated by the question
106+
### Time - O(n)
107+
- We need to loop through the elements of the given array 2 times
108+
- 1 time to obtain the **prefix product array**, another time to calculate the suffix to obtain the final answer
109+
110+
111+
## Personal Reflection
112+
---
113+
- **Why it takes so long to solve:** Didn't read the problem carefully and implementing [[Prefix Sum (前缀和)]] on products of elements
114+
- **What you could have done better:** Sketch out the calculation process clearly on the paper
115+
- **What you missed:** *NIL*
116+
- **Ideas you've seen before:** Prefix Sum (前缀和)
117+
- **Ideas you found here that could help you later:** Prefix Sum (前缀和)'s ability to provide the product of a range of elements in O(1)
118+
- **Ideas that didn't work and why:** *NIL*

content/cp/prefix_sum/Product of Array Except Self.md

Lines changed: 0 additions & 89 deletions
This file was deleted.
Binary file not shown.

content/cp/prefix_sum/assets/product_of_array_except_self.svg

Lines changed: 8 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)