Skip to content

Commit 380cf1f

Browse files
Merge pull request #104 from romankurnovskii/problems-216-328-374-437-649-700-714-735-790-872-875-1161-1268-1318-1448-1466-2095-2130-2300-2336
Add solutions and explanations for problems 216, 328, 374, 437, 649, 700, 714, 735, 790, 872, 875, 1161, 1268, 1318, 1448, 1466, 2095, 2130, 2300, 2336
2 parents 01fb8a2 + 3c61215 commit 380cf1f

File tree

41 files changed

+1833
-119
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1833
-119
lines changed

data/book-sets.json

Lines changed: 119 additions & 119 deletions
Large diffs are not rendered by default.

explanations/1161/en.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
## Explanation
2+
3+
### Strategy (The "Why")
4+
5+
**1.1 Constraints & Complexity:**
6+
7+
* **Input Size:** The tree can have up to 10^4 nodes.
8+
* **Time Complexity:** O(n) - We visit each node once using BFS, where n is the number of nodes.
9+
* **Space Complexity:** O(w) where w is the maximum width of the tree. In worst case O(n).
10+
* **Edge Case:** If the tree is empty, return 0. If all level sums are equal, return the smallest level (1).
11+
12+
**1.2 High-level approach:**
13+
14+
The goal is to find the level with the maximum sum of node values. We use BFS (level-order traversal) to process nodes level by level and track the sum for each level.
15+
16+
![BFS traversal showing level-by-level processing and sum calculation]
17+
18+
**1.3 Brute force vs. optimized strategy:**
19+
20+
* **Brute Force:** Use DFS to collect all nodes by level, then calculate sums. This requires extra space to store level information.
21+
* **Optimized (BFS):** Use BFS to process one level at a time, calculating the sum as we go. This is O(n) time and naturally processes levels in order.
22+
* **Why it's better:** BFS naturally processes levels sequentially, making it straightforward to track level sums without extra data structures.
23+
24+
**1.4 Decomposition:**
25+
26+
1. Use a queue for BFS traversal.
27+
2. For each level:
28+
- Process all nodes at the current level.
29+
- Sum their values.
30+
- Track the maximum sum and corresponding level.
31+
3. Return the smallest level with maximum sum.
32+
33+
### Steps (The "How")
34+
35+
**2.1 Initialization & Example Setup:**
36+
37+
Let's use the example: root = [1,7,0,7,-8,null,null]
38+
39+
We initialize:
40+
* `queue = deque([root])`
41+
* `max_sum = -inf`
42+
* `res = 1`
43+
* `level = 1`
44+
45+
**2.2 Start Checking/Processing:**
46+
47+
We enter a while loop while the queue is not empty.
48+
49+
**2.3 Trace Walkthrough:**
50+
51+
| Level | Nodes | Level Sum | max_sum | res |
52+
|-------|-------|-----------|---------|-----|
53+
| 1 | [1] | 1 | 1 | 1 |
54+
| 2 | [7, 0] | 7 | 7 | 2 |
55+
| 3 | [7, -8] | -1 | 7 | 2 |
56+
57+
**2.4 Increment and Loop:**
58+
59+
After processing each level, we increment the level counter and continue to the next level.
60+
61+
**2.5 Return Result:**
62+
63+
After processing all levels, `res = 2` is returned (level 2 has maximum sum of 7).
64+

explanations/1268/en.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
## Explanation
2+
3+
### Strategy (The "Why")
4+
5+
**1.1 Constraints & Complexity:**
6+
7+
* **Input Size:** Products array can have up to 1000 strings, each up to 3000 characters. SearchWord can be up to 1000 characters.
8+
* **Time Complexity:** O(m * log m + n * m) where m is products length and n is searchWord length. Sorting takes O(m log m), and for each character we scan products.
9+
* **Space Complexity:** O(m) for sorted products plus O(n * 3) for results.
10+
* **Edge Case:** If no products match a prefix, return an empty list for that prefix.
11+
12+
**1.2 High-level approach:**
13+
14+
The goal is to suggest up to 3 products that have a common prefix with the search word as each character is typed. We sort products first, then for each prefix, find matching products.
15+
16+
![Prefix matching showing how products are filtered as each character is typed]
17+
18+
**1.3 Brute force vs. optimized strategy:**
19+
20+
* **Brute Force:** For each prefix, scan all products and filter those starting with the prefix. This is O(n * m) where n is searchWord length.
21+
* **Optimized (Sorting + Linear Scan):** Sort products once, then for each prefix, scan from the beginning and collect up to 3 matches. This is O(m log m + n * m).
22+
* **Why it's better:** Sorting ensures we get lexicographically minimum products first, and we can stop after finding 3 matches.
23+
24+
**1.4 Decomposition:**
25+
26+
1. Sort the products array lexicographically.
27+
2. For each character in searchWord:
28+
- Build the current prefix.
29+
- Scan products from the beginning.
30+
- Collect products that start with the prefix (up to 3).
31+
- Add to results.
32+
3. Return the list of suggestion lists.
33+
34+
### Steps (The "How")
35+
36+
**2.1 Initialization & Example Setup:**
37+
38+
Let's use the example: products = ["mobile","mouse","moneypot","monitor","mousepad"], searchWord = "mouse"
39+
40+
We initialize:
41+
* Sort products: ["mobile","moneypot","monitor","mouse","mousepad"]
42+
* `res = []`
43+
* `prefix = ""`
44+
45+
**2.2 Start Checking/Processing:**
46+
47+
We iterate through each character in searchWord.
48+
49+
**2.3 Trace Walkthrough:**
50+
51+
| Char | prefix | Matching Products | Suggestions |
52+
|------|--------|-------------------|-------------|
53+
| 'm' | "m" | mobile, moneypot, monitor | ["mobile","moneypot","monitor"] |
54+
| 'o' | "mo" | mobile, moneypot, monitor | ["mobile","moneypot","monitor"] |
55+
| 'u' | "mou" | mouse, mousepad | ["mouse","mousepad"] |
56+
| 's' | "mous" | mouse, mousepad | ["mouse","mousepad"] |
57+
| 'e' | "mouse" | mouse, mousepad | ["mouse","mousepad"] |
58+
59+
**2.4 Increment and Loop:**
60+
61+
After processing each character, we append the suggestions list to results and continue.
62+
63+
**2.5 Return Result:**
64+
65+
After processing all characters, `res = [["mobile","moneypot","monitor"], ["mobile","moneypot","monitor"], ["mouse","mousepad"], ["mouse","mousepad"], ["mouse","mousepad"]]` is returned.
66+

explanations/1318/en.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
## Explanation
2+
3+
### Strategy (The "Why")
4+
5+
**1.1 Constraints & Complexity:**
6+
7+
* **Input Size:** a, b, and c can be up to 10^9.
8+
* **Time Complexity:** O(log(max(a,b,c))) - We process each bit position, and the number of bits is logarithmic in the value.
9+
* **Space Complexity:** O(1) - We only use a constant amount of extra space.
10+
* **Edge Case:** If a OR b already equals c, return 0 (no flips needed).
11+
12+
**1.2 High-level approach:**
13+
14+
The goal is to find the minimum number of bit flips needed to make (a OR b) equal to c. We check each bit position and determine how many flips are needed.
15+
16+
![Bit manipulation showing how each bit position is checked and flipped]
17+
18+
**1.3 Brute force vs. optimized strategy:**
19+
20+
* **Brute Force:** Try all possible combinations of bit flips. This is exponential.
21+
* **Optimized (Bit-by-bit Check):** Check each bit position independently. For each position, if (a_bit OR b_bit) != c_bit, calculate the minimum flips needed. This is O(log(max(a,b,c))) time.
22+
* **Why it's better:** Bit positions are independent, so we can process them separately and sum the flips needed.
23+
24+
**1.4 Decomposition:**
25+
26+
1. Initialize result counter to 0.
27+
2. While any of a, b, or c is non-zero:
28+
- Extract the least significant bit of each.
29+
- Check if (a_bit OR b_bit) equals c_bit.
30+
- If not, calculate flips needed:
31+
- If c_bit is 1: flip one of a or b (1 flip).
32+
- If c_bit is 0: flip both a and b if they're both 1 (2 flips), or flip the one that's 1 (1 flip).
33+
- Right-shift all numbers.
34+
3. Return total flips.
35+
36+
### Steps (The "How")
37+
38+
**2.1 Initialization & Example Setup:**
39+
40+
Let's use the example: a = 2 (binary 10), b = 6 (binary 110), c = 5 (binary 101)
41+
42+
We initialize:
43+
* `res = 0`
44+
45+
**2.2 Start Checking/Processing:**
46+
47+
We enter a while loop while any number is non-zero.
48+
49+
**2.3 Trace Walkthrough:**
50+
51+
| Bit Pos | a_bit | b_bit | c_bit | a OR b | Match? | Flips Needed | res |
52+
|---------|-------|-------|-------|--------|-------|--------------|-----|
53+
| 0 | 0 | 0 | 1 | 0 | No | 1 (set a or b) | 1 |
54+
| 1 | 1 | 1 | 0 | 1 | No | 2 (clear both) | 3 |
55+
| 2 | 0 | 1 | 1 | 1 | Yes | 0 | 3 |
56+
57+
**2.4 Increment and Loop:**
58+
59+
After processing each bit, we right-shift all numbers and continue.
60+
61+
**2.5 Return Result:**
62+
63+
After processing all bits, `res = 3` is returned.
64+

explanations/1448/en.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
## Explanation
2+
3+
### Strategy (The "Why")
4+
5+
**1.1 Constraints & Complexity:**
6+
7+
* **Input Size:** The tree can have up to 10^5 nodes.
8+
* **Time Complexity:** O(n) - We visit each node once using DFS, where n is the number of nodes.
9+
* **Space Complexity:** O(h) for the recursion stack where h is the height. In worst case O(n).
10+
* **Edge Case:** The root is always a good node since there are no nodes above it.
11+
12+
**1.2 High-level approach:**
13+
14+
The goal is to count nodes where the path from root to that node has no node with value greater than the current node. We use DFS to traverse the tree, tracking the maximum value seen so far.
15+
16+
![Tree traversal showing how we track maximum values along paths]
17+
18+
**1.3 Brute force vs. optimized strategy:**
19+
20+
* **Brute Force:** For each node, check all nodes on the path from root to it. This is O(n^2) in worst case.
21+
* **Optimized (DFS with Max Tracking):** During DFS, pass the maximum value seen so far. If current node's value >= max, it's good. This is O(n) time.
22+
* **Why it's better:** We check the condition during traversal without storing paths, making it O(n) instead of O(n^2).
23+
24+
**1.4 Decomposition:**
25+
26+
1. Use DFS to traverse the tree.
27+
2. For each node, check if its value >= max_value_seen.
28+
3. If yes, increment the count and update max_value_seen.
29+
4. Recursively process left and right children with updated max_value.
30+
5. Return the total count.
31+
32+
### Steps (The "How")
33+
34+
**2.1 Initialization & Example Setup:**
35+
36+
Let's use the example: root = [3,1,4,3,null,1,5]
37+
38+
We initialize:
39+
* `res = 0`
40+
* Start DFS from root with `max_val = 3` (root value)
41+
42+
**2.2 Start Checking/Processing:**
43+
44+
We call `dfs(root, root.val)`.
45+
46+
**2.3 Trace Walkthrough:**
47+
48+
| Node | Value | max_val | Value >= max? | Action | res |
49+
|------|-------|---------|---------------|--------|-----|
50+
| 3 | 3 | 3 | Yes | Count++, max=3 | 1 |
51+
| 1 | 1 | 3 | No | Skip | 1 |
52+
| 3 | 3 | 3 | Yes | Count++, max=3 | 2 |
53+
| 4 | 4 | 3 | Yes | Count++, max=4 | 3 |
54+
| 1 | 1 | 4 | No | Skip | 3 |
55+
| 5 | 5 | 4 | Yes | Count++, max=5 | 4 |
56+
57+
**2.4 Increment and Loop:**
58+
59+
After processing each node, we recursively process its children.
60+
61+
**2.5 Return Result:**
62+
63+
After processing all nodes, `res = 4` is returned (nodes 3, 3, 4, and 5 are good).
64+

explanations/1466/en.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
## Explanation
2+
3+
### Strategy (The "Why")
4+
5+
**1.1 Constraints & Complexity:**
6+
7+
* **Input Size:** n can be up to 5 * 10^4, and there are n-1 connections.
8+
* **Time Complexity:** O(n) - We build the graph and traverse it once using DFS.
9+
* **Space Complexity:** O(n) - We store the graph and use O(n) for recursion stack.
10+
* **Edge Case:** If all roads already point toward city 0, return 0.
11+
12+
**1.2 High-level approach:**
13+
14+
The goal is to find the minimum number of road reversals needed so all cities can reach city 0. We treat the graph as undirected and use DFS from city 0, counting roads that need reversal.
15+
16+
![Graph traversal showing which roads need to be reversed]
17+
18+
**1.3 Brute force vs. optimized strategy:**
19+
20+
* **Brute Force:** Try all possible combinations of road reversals. This is exponential.
21+
* **Optimized (DFS from Root):** Treat graph as undirected, start DFS from city 0. When traversing an edge in the original direction (away from 0), it needs reversal. This is O(n) time.
22+
* **Why it's better:** We only need one DFS traversal to identify all roads that need reversal, making it O(n) instead of exponential.
23+
24+
**1.4 Decomposition:**
25+
26+
1. Build an undirected graph from connections, marking original direction.
27+
2. Start DFS from city 0.
28+
3. For each edge traversed:
29+
- If the edge was originally directed away from the current node (toward 0), it's correct, no reversal needed.
30+
- If the edge was originally directed toward the current node (away from 0), it needs reversal, increment count.
31+
4. Return the count.
32+
33+
### Steps (The "How")
34+
35+
**2.1 Initialization & Example Setup:**
36+
37+
Let's use the example: n = 6, connections = [[0,1],[1,3],[2,3],[4,0],[4,5]]
38+
39+
We initialize:
40+
* Build graph:
41+
- 0: [(1,0)] (edge to 1, original direction)
42+
- 1: [(0,0), (3,1)]
43+
- 2: [(3,1)]
44+
- 3: [(1,0), (2,0)]
45+
- 4: [(0,1), (5,1)]
46+
- 5: [(4,0)]
47+
* `res = 0`
48+
49+
**2.2 Start Checking/Processing:**
50+
51+
We call `dfs(0, -1)` starting from city 0.
52+
53+
**2.3 Trace Walkthrough:**
54+
55+
| Current | Neighbor | Direction | Action | res |
56+
|---------|----------|-----------|--------|-----|
57+
| 0 | 1 | 0 (toward 0) | Correct, no reversal | 0 |
58+
| 1 | 3 | 1 (away from 0) | Needs reversal | 1 |
59+
| 3 | 2 | 1 (away from 0) | Needs reversal | 2 |
60+
| 0 | 4 | 1 (away from 0) | Wait, from 0's perspective... | |
61+
| 4 | 0 | 1 (toward 0) | Correct | 2 |
62+
| 4 | 5 | 1 (away from 0) | Needs reversal | 3 |
63+
64+
**2.4 Increment and Loop:**
65+
66+
After processing each edge, we continue DFS to the next city.
67+
68+
**2.5 Return Result:**
69+
70+
After processing all cities, `res = 3` is returned (roads [1,3], [2,3], and [4,5] need reversal).
71+

0 commit comments

Comments
 (0)