Skip to content

Commit 298c7df

Browse files
upd
1 parent 60ef982 commit 298c7df

File tree

20 files changed

+539
-0
lines changed

20 files changed

+539
-0
lines changed

explanations/237/en.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
## Explanation
2+
3+
### Strategy
4+
5+
**Restate the problem**
6+
7+
We need to delete a node from a linked list, but we are only given access to the node to be deleted (not the head). We cannot access the previous node directly.
8+
9+
**1.1 Constraints & Complexity**
10+
11+
- **Input Size:** The linked list has 2 to 1000 nodes.
12+
- **Time Complexity:** O(1) - We only perform a constant number of operations.
13+
- **Space Complexity:** O(1) - No additional space is used.
14+
- **Edge Case:** The node to delete is guaranteed not to be the tail node, so we can safely access node.next.next.
15+
16+
**1.2 High-level approach**
17+
18+
Since we cannot access the previous node, we cannot directly unlink the current node. Instead, we copy the value from the next node into the current node, then skip the next node by linking the current node to the node after the next one.
19+
20+
![Linked list node deletion by copying value](https://assets.leetcode.com/uploads/2020/09/01/node1.jpg)
21+
22+
**1.3 Brute force vs. optimized strategy**
23+
24+
- **Brute Force:** If we had access to the head, we could traverse to find the previous node and update its next pointer. This would be O(n) time.
25+
- **Optimized Strategy:** Copy the next node's value to the current node and skip the next node. This is O(1) time.
26+
- **Why optimized is better:** We achieve constant time deletion by cleverly copying data instead of restructuring the list.
27+
28+
**1.4 Decomposition**
29+
30+
1. **Copy Value:** Copy the value from node.next to node.
31+
2. **Skip Next Node:** Update node.next to point to node.next.next, effectively removing the next node from the list.
32+
33+
### Steps
34+
35+
**2.1 Initialization & Example Setup**
36+
37+
Let's use the example: `head = [4,5,1,9]`, `node = 5` (the node with value 5)
38+
39+
- The linked list: 4 → 5 → 1 → 9
40+
- We are given the node containing value 5 (second node)
41+
42+
**2.2 Start Processing**
43+
44+
We need to delete the node with value 5. Since we only have access to this node, we cannot modify the previous node (4).
45+
46+
**2.3 Trace Walkthrough**
47+
48+
| Step | Current Node Value | Next Node Value | Action | Result |
49+
|------|-------------------|-----------------|--------|--------|
50+
| Initial | 5 | 1 | - | 4 → 5 → 1 → 9 |
51+
| Copy | 5 → 1 | 1 | Copy next value | 4 → 1 → 1 → 9 |
52+
| Skip | 1 | 9 | Link to next.next | 4 → 1 → 9 |
53+
54+
**2.4 Update Pointers**
55+
56+
After copying the value, we update `node.next = node.next.next`, which removes the duplicate node from the list.
57+
58+
**2.5 Return Result**
59+
60+
The list becomes `[4,1,9]`, effectively deleting the original node with value 5. Note that we actually deleted the next node, but from the user's perspective, the node with value 5 is gone.

explanations/2482/en.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
## Explanation
2+
3+
### Strategy
4+
5+
**Restate the problem**
6+
7+
We are given a binary matrix and need to create a difference matrix where each cell `diff[i][j]` is calculated as: ones in row i + ones in column j - zeros in row i - zeros in column j.
8+
9+
**1.1 Constraints & Complexity**
10+
11+
- **Input Size:** The matrix can have up to 10^5 rows and columns, with total cells up to 10^5.
12+
- **Time Complexity:** O(m*n) - We need to traverse the matrix twice: once to count ones in rows and columns, and once to build the result matrix.
13+
- **Space Complexity:** O(m + n) - We store arrays for row and column counts.
14+
- **Edge Case:** Empty matrix or single cell matrix are handled naturally by the algorithm.
15+
16+
**1.2 High-level approach**
17+
18+
The goal is to compute the difference matrix efficiently by precomputing row and column statistics. Instead of recalculating counts for each cell, we count ones in each row and column once, then use these counts to compute each cell's value.
19+
20+
![Matrix showing row and column counts with difference calculation](https://assets.leetcode.com/uploads/2022/11/06/image-20221106171729-5.png)
21+
22+
**1.3 Brute force vs. optimized strategy**
23+
24+
- **Brute Force:** For each cell (i, j), count ones and zeros in row i and column j separately. This results in O(m*n*(m+n)) time complexity, which is inefficient.
25+
- **Optimized Strategy:** Precompute ones count for all rows and columns in O(m*n) time, then compute each cell in O(1) time using the precomputed values. Total time is O(m*n).
26+
- **Why optimized is better:** We avoid redundant calculations by reusing row and column statistics across all cells in the same row or column.
27+
28+
**1.4 Decomposition**
29+
30+
1. **Count Row Statistics:** Traverse the matrix once to count the number of ones in each row.
31+
2. **Count Column Statistics:** During the same traversal, count the number of ones in each column.
32+
3. **Calculate Zeros:** For each row, zeros = total columns - ones. For each column, zeros = total rows - ones.
33+
4. **Build Result Matrix:** For each cell (i, j), compute diff[i][j] = ones_row[i] + ones_col[j] - zeros_row[i] - zeros_col[j].
34+
35+
### Steps
36+
37+
**2.1 Initialization & Example Setup**
38+
39+
Let's use the example: `grid = [[0,1,1],[1,0,1],[0,0,1]]`
40+
41+
- Matrix dimensions: 3 rows × 3 columns
42+
- Initialize `ones_row = [0, 0, 0]` and `ones_col = [0, 0, 0]`
43+
44+
**2.2 Start Counting**
45+
46+
Traverse the matrix to count ones:
47+
- Row 0: [0,1,1] → ones_row[0] = 2
48+
- Row 1: [1,0,1] → ones_row[1] = 2
49+
- Row 2: [0,0,1] → ones_row[2] = 1
50+
51+
- Column 0: [0,1,0] → ones_col[0] = 1
52+
- Column 1: [1,0,0] → ones_col[1] = 1
53+
- Column 2: [1,1,1] → ones_col[2] = 3
54+
55+
**2.3 Trace Walkthrough**
56+
57+
| Cell (i,j) | ones_row[i] | ones_col[j] | zeros_row[i] | zeros_col[j] | diff[i][j] |
58+
|------------|-------------|-------------|--------------|--------------|------------|
59+
| (0,0) | 2 | 1 | 1 | 2 | 2+1-1-2 = 0 |
60+
| (0,1) | 2 | 1 | 1 | 2 | 2+1-1-2 = 0 |
61+
| (0,2) | 2 | 3 | 1 | 0 | 2+3-1-0 = 4 |
62+
| (1,0) | 2 | 1 | 1 | 2 | 2+1-1-2 = 0 |
63+
| (1,1) | 2 | 1 | 1 | 2 | 2+1-1-2 = 0 |
64+
| (1,2) | 2 | 3 | 1 | 0 | 2+3-1-0 = 4 |
65+
| (2,0) | 1 | 1 | 2 | 2 | 1+1-2-2 = -2 |
66+
| (2,1) | 1 | 1 | 2 | 2 | 1+1-2-2 = -2 |
67+
| (2,2) | 1 | 3 | 2 | 0 | 1+3-2-0 = 2 |
68+
69+
**2.4 Build Result**
70+
71+
Create result matrix `res` with dimensions 3×3 and fill each cell using the formula.
72+
73+
**2.5 Return Result**
74+
75+
Return `[[0,0,4],[0,0,4],[-2,-2,2]]`, which matches the expected output.

explanations/797/en.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
## Explanation
2+
3+
### Strategy
4+
5+
**Restate the problem**
6+
7+
We need to find all paths from node 0 to node n-1 in a directed acyclic graph (DAG). Each path is a sequence of nodes connected by edges.
8+
9+
**1.1 Constraints & Complexity**
10+
11+
- **Input Size:** The graph has 2 to 15 nodes.
12+
- **Time Complexity:** O(2^n * n) - In the worst case, there can be exponentially many paths, and each path can have up to n nodes.
13+
- **Space Complexity:** O(2^n * n) - We need to store all paths, and the recursion stack can go up to n levels.
14+
- **Edge Case:** If there are no paths from 0 to n-1, we return an empty list.
15+
16+
**1.2 High-level approach**
17+
18+
Use depth-first search (DFS) to explore all possible paths from the source node (0) to the target node (n-1). As we traverse, we maintain the current path and add it to results when we reach the destination.
19+
20+
![Graph showing all paths from source to target](https://assets.leetcode.com/uploads/2020/09/28/all_1.jpg)
21+
22+
**1.3 Brute force vs. optimized strategy**
23+
24+
- **Brute Force:** Generate all possible paths and filter those that end at n-1. This is inefficient and doesn't leverage the DAG structure.
25+
- **Optimized Strategy:** Use DFS with backtracking to explore paths incrementally, only following edges that can potentially lead to the target. This naturally finds all valid paths.
26+
- **Why optimized is better:** DFS with backtracking efficiently explores the graph structure without redundant computations, and backtracking allows us to reuse the path list.
27+
28+
**1.4 Decomposition**
29+
30+
1. **Initialize Result:** Create an empty list to store all paths.
31+
2. **Start DFS:** Begin DFS from node 0 with an initial path containing just node 0.
32+
3. **Explore Neighbors:** For each neighbor of the current node, add it to the path and recursively explore.
33+
4. **Record Complete Paths:** When we reach node n-1, add the current path to results.
34+
5. **Backtrack:** After exploring a neighbor, remove it from the path to try other paths.
35+
36+
### Steps
37+
38+
**2.1 Initialization & Example Setup**
39+
40+
Let's use the example: `graph = [[1,2],[3],[3],[]]`
41+
42+
- Nodes: 0, 1, 2, 3
43+
- Edges: 0→1, 0→2, 1→3, 2→3
44+
- Target: node 3
45+
46+
**2.2 Start DFS**
47+
48+
Initialize `res = []` and start DFS from node 0 with `path = [0]`.
49+
50+
**2.3 Trace Walkthrough**
51+
52+
| Current Node | Path | Neighbors | Action | Result |
53+
|-------------|------|-----------|--------|--------|
54+
| 0 | [0] | [1,2] | Explore 1 | - |
55+
| 1 | [0,1] | [3] | Explore 3 | - |
56+
| 3 | [0,1,3] | [] | Reached target! | Add [0,1,3] |
57+
| 1 | [0,1] | [3] | Backtrack | - |
58+
| 0 | [0] | [1,2] | Explore 2 | - |
59+
| 2 | [0,2] | [3] | Explore 3 | - |
60+
| 3 | [0,2,3] | [] | Reached target! | Add [0,2,3] |
61+
62+
**2.4 Backtrack and Continue**
63+
64+
After finding path [0,1,3], we backtrack by removing 3 and 1 from the path, returning to node 0. Then we explore the other neighbor (2) to find [0,2,3].
65+
66+
**2.5 Return Result**
67+
68+
After DFS completes, `res = [[0,1,3],[0,2,3]]`, which contains all paths from node 0 to node 3.

solutions/1008/01.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Definition for a binary tree node.
2+
# class TreeNode:
3+
# def __init__(self, val=0, left=None, right=None):
4+
# self.val = val
5+
# self.left = left
6+
# self.right = right
7+
class Solution:
8+
def bstFromPreorder(self, preorder: List[int]) -> Optional[TreeNode]:
9+
if not preorder:
10+
return None
11+
12+
root = TreeNode(preorder[0])
13+
stack = [root]
14+
15+
for val in preorder[1:]:
16+
node = TreeNode(val)
17+
18+
# If current value is less than stack top, it's left child
19+
if val < stack[-1].val:
20+
stack[-1].left = node
21+
else:
22+
# Find the parent where this node should be right child
23+
while stack and stack[-1].val < val:
24+
parent = stack.pop()
25+
parent.right = node
26+
27+
stack.append(node)
28+
29+
return root

solutions/1079/01.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
class Solution:
2+
def numTilePossibilities(self, tiles: str) -> int:
3+
from collections import Counter
4+
5+
def backtrack(count):
6+
res = 0
7+
for char in count:
8+
if count[char] > 0:
9+
res += 1 # Count this sequence
10+
count[char] -= 1
11+
res += backtrack(count) # Continue building
12+
count[char] += 1 # Backtrack
13+
return res
14+
15+
count = Counter(tiles)
16+
return backtrack(count)

solutions/1261/01.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Definition for a binary tree node.
2+
# class TreeNode:
3+
# def __init__(self, val=0, left=None, right=None):
4+
# self.val = val
5+
# self.left = left
6+
# self.right = right
7+
class FindElements:
8+
9+
def __init__(self, root: Optional[TreeNode]):
10+
self.values = set()
11+
12+
def recover(node, val):
13+
if not node:
14+
return
15+
node.val = val
16+
self.values.add(val)
17+
recover(node.left, 2 * val + 1)
18+
recover(node.right, 2 * val + 2)
19+
20+
recover(root, 0)
21+
22+
def find(self, target: int) -> bool:
23+
return target in self.values
24+
25+
26+
# Your FindElements object will be instantiated and called as such:
27+
# obj = FindElements(root)
28+
# param_1 = obj.find(target)

solutions/1326/01.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
class Solution:
2+
def minTaps(self, n: int, ranges: List[int]) -> int:
3+
# Create intervals
4+
intervals = []
5+
for i in range(n + 1):
6+
if ranges[i] > 0:
7+
left = max(0, i - ranges[i])
8+
right = min(n, i + ranges[i])
9+
intervals.append((left, right))
10+
11+
if not intervals:
12+
return -1
13+
14+
# Sort by left endpoint
15+
intervals.sort()
16+
17+
res = 0
18+
covered = 0
19+
i = 0
20+
21+
while covered < n:
22+
max_right = covered
23+
# Find interval that starts <= covered and extends farthest
24+
while i < len(intervals) and intervals[i][0] <= covered:
25+
max_right = max(max_right, intervals[i][1])
26+
i += 1
27+
28+
if max_right == covered:
29+
return -1 # Cannot extend coverage
30+
31+
covered = max_right
32+
res += 1
33+
34+
return res

solutions/1347/01.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
class Solution:
2+
def minSteps(self, s: str, t: str) -> int:
3+
from collections import Counter
4+
5+
count_s = Counter(s)
6+
count_t = Counter(t)
7+
8+
res = 0
9+
for char in count_s:
10+
if count_s[char] > count_t[char]:
11+
res += count_s[char] - count_t[char]
12+
13+
return res

solutions/1551/01.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class Solution:
2+
def findMinFibonacciNumbers(self, k: int) -> int:
3+
# Generate Fibonacci numbers up to k
4+
fib = [1, 1]
5+
while fib[-1] < k:
6+
fib.append(fib[-1] + fib[-2])
7+
8+
# Greedy: use largest Fibonacci number <= remaining k
9+
res = 0
10+
idx = len(fib) - 1
11+
while k > 0:
12+
while fib[idx] > k:
13+
idx -= 1
14+
k -= fib[idx]
15+
res += 1
16+
17+
return res

solutions/1605/01.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class Solution:
2+
def restoreMatrix(self, rowSum: List[int], colSum: List[int]) -> List[List[int]]:
3+
m, n = len(rowSum), len(colSum)
4+
res = [[0] * n for _ in range(m)]
5+
6+
for i in range(m):
7+
for j in range(n):
8+
# Place minimum of remaining row sum and column sum
9+
val = min(rowSum[i], colSum[j])
10+
res[i][j] = val
11+
rowSum[i] -= val
12+
colSum[j] -= val
13+
14+
return res

0 commit comments

Comments
 (0)