Skip to content

Commit ec795ba

Browse files
author
Wasim
committed
docs: add 12 detailed pattern deep dives
1 parent abafcd8 commit ec795ba

12 files changed

Lines changed: 835 additions & 0 deletions
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Understanding the Fast & Slow Pointers Concept
2+
3+
Think of the Fast & Slow Pointers technique like two runners on a track. One is a sprinter (Fast), moving two steps at a time, and the other is a jogger (Slow), moving one step at a time. If the track is a straight line, the fast runner will reach the finish line when the slow runner is exactly at the halfway mark. If the track is a circle (a cycle), the fast runner will eventually lap the slow runner and they will meet.
4+
5+
This technique, also known as Floyd's Cycle-Finding Algorithm or the "Hare & Tortoise" algorithm, is used primarily to traverse linked lists and arrays where loops or middle points need to be identified without using extra memory.
6+
7+
There are two primary uses:
8+
1. **Finding a Cycle** (Determining if a loop exists).
9+
2. **Finding the Middle** (Locating the midpoint of a list).
10+
11+
## Type 1: Finding a Cycle
12+
We initialize two pointers, `Slow` and `Fast`, at the head of the data structure. `Slow` moves one step, and `Fast` moves two steps. If there is a cycle, the `Fast` pointer will loop around and eventually point to the same node as the `Slow` pointer.
13+
14+
### The Process Step-by-Step
15+
**Goal:** Detect if a cycle exists in the linked list `1 -> 2 -> 3 -> 4 -> 5 -> 3` (where 5 points back to 3).
16+
17+
```plaintext
18+
Data: 1 -> 2 -> 3 -> 4 -> 5
19+
^ |
20+
|---------| (Cycle back to 3)
21+
22+
Step 1: [1] -> 2 -> 3 -> 4 -> 5
23+
^S
24+
^F (Start: Both at 1)
25+
26+
Step 2: 1 -> [2] -> [3] -> 4 -> 5
27+
^S ^F (Slow moves to 2, Fast moves to 3)
28+
29+
Step 3: 1 -> 2 -> [3] -> 4 -> [5]
30+
^S ^F (Slow moves to 3, Fast moves to 5)
31+
32+
Step 4: 1 -> 2 -> 3 -> [4] -> 5
33+
^S (Fast loops to 3, moves to 4. Slow moves to 4)
34+
^F
35+
36+
Result: Slow and Fast are both at 4. A cycle is detected!
37+
```
38+
39+
## Type 2: Finding the Middle
40+
Here, we also start both pointers at the head. We let the `Fast` pointer run until it hits the end of the list (or `null`). By the time `Fast` reaches the end, `Slow` will be exactly in the middle.
41+
42+
### The Process Step-by-Step
43+
**Goal:** Find the middle element of the linked list `1 -> 2 -> 3 -> 4 -> 5`.
44+
45+
```plaintext
46+
Data: 1 -> 2 -> 3 -> 4 -> 5 -> null
47+
48+
Step 1: [1] -> 2 -> 3 -> 4 -> 5 -> null
49+
^S
50+
^F
51+
52+
Step 2: 1 -> [2] -> [3] -> 4 -> 5 -> null
53+
^S ^F
54+
55+
Step 3: 1 -> 2 -> [3] -> 4 -> [5] -> null
56+
^S ^F
57+
58+
Step 4: Fast cannot move two steps anymore because its next is null.
59+
60+
Result: Slow is pointing at 3, which is the exact middle of the list!
61+
```
62+
63+
### Comparison Summary
64+
| Feature | Finding a Cycle | Finding the Middle |
65+
|---------|-----------------|--------------------|
66+
| **Setup** | `Slow` at head, `Fast` at head. | `Slow` at head, `Fast` at head. |
67+
| **Movement** | `Slow` +1, `Fast` +2. | `Slow` +1, `Fast` +2. |
68+
| **Termination** | `Slow == Fast` or `Fast == null`. | `Fast == null` or `Fast.next == null`. |
69+
| **Used For...** | Detecting loops, finding cycle start. | Finding midpoints, palindromes. |
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Understanding the Merge Intervals Concept
2+
3+
Think of Merge Intervals like booking meetings in a conference room on a calendar. If you have one meeting from 1:00 PM to 3:00 PM and another meeting from 2:00 PM to 4:00 PM, they overlap. Instead of keeping them separate, you combine them into a single blocked-out block from 1:00 PM to 4:00 PM.
4+
5+
This technique involves dealing with sets of overlapping intervals. The trick is to **sort the intervals** by their starting points first. Once sorted, any overlapping intervals will be right next to each other, allowing you to merge them in a single pass.
6+
7+
There are two primary operations:
8+
1. **Merging Overlapping Intervals** (Combining intervals that intersect).
9+
2. **Finding Intersecting Intervals** (Finding common overlaps between lists).
10+
11+
## Type 1: Merging Overlapping Intervals
12+
First, we sort the array of intervals based on their start values. Then, we take the first interval and compare its end value with the next interval's start value. If they overlap, we merge them by taking the maximum end value.
13+
14+
### The Process Step-by-Step
15+
**Goal:** Merge the intervals `[[1, 3], [2, 6], [8, 10], [15, 18]]`.
16+
17+
```plaintext
18+
Data: [[1, 3], [2, 6], [8, 10], [15, 18]]
19+
(Already sorted by start times: 1, 2, 8, 15)
20+
21+
Step 1: Current = [1, 3]
22+
Compare with [2, 6].
23+
Does 2 <= 3? Yes! Overlap exists.
24+
Merge: Start = 1, End = max(3, 6) = 6.
25+
New Current = [1, 6]
26+
27+
Step 2: Current = [1, 6]
28+
Compare with [8, 10].
29+
Does 8 <= 6? No! No overlap.
30+
Push [1, 6] to Result.
31+
New Current = [8, 10]
32+
33+
Step 3: Current = [8, 10]
34+
Compare with [15, 18].
35+
Does 15 <= 10? No! No overlap.
36+
Push [8, 10] to Result.
37+
New Current = [15, 18]
38+
39+
Step 4: End of list. Push final Current [15, 18] to Result.
40+
41+
Result: [[1, 6], [8, 10], [15, 18]]
42+
```
43+
44+
## Type 2: Inserting a New Interval
45+
When inserting a new interval into a list of already non-overlapping intervals, you iterate through the list. You add intervals that come before the new one, merge the overlapping ones by updating the new interval's bounds, and then add the remaining intervals.
46+
47+
### The Process Step-by-Step
48+
**Goal:** Insert `[4, 8]` into `[[1, 2], [3, 5], [6, 7], [8, 10], [12, 16]]`.
49+
50+
```plaintext
51+
New Interval: [4, 8]
52+
Data: [[1, 2], [3, 5], [6, 7], [8, 10], [12, 16]]
53+
54+
Step 1: Compare [1, 2] with [4, 8]. Ends before 4.
55+
Add [1, 2] to Result.
56+
57+
Step 2: Compare [3, 5] with [4, 8]. Overlaps!
58+
Merge: [min(3, 4), max(5, 8)] = [3, 8].
59+
New Interval is now [3, 8].
60+
61+
Step 3: Compare [6, 7] with [3, 8]. Overlaps!
62+
Merge: [min(6, 3), max(7, 8)] = [3, 8].
63+
New Interval remains [3, 8].
64+
65+
Step 4: Compare [8, 10] with [3, 8]. Overlaps!
66+
Merge: [min(8, 3), max(10, 8)] = [3, 10].
67+
New Interval is now [3, 10].
68+
69+
Step 5: Compare [12, 16] with [3, 10]. Starts after 10.
70+
Add merged New Interval [3, 10] to Result.
71+
Add [12, 16] to Result.
72+
73+
Result: [[1, 2], [3, 10], [12, 16]]
74+
```
75+
76+
### Comparison Summary
77+
| Feature | Merging All Overlaps | Inserting New Interval |
78+
|---------|----------------------|------------------------|
79+
| **Prerequisite** | Must sort intervals by start time. | Existing list is already sorted. |
80+
| **Logic** | `next.start <= current.end` | `current.end < new.start` or `current.start > new.end` |
81+
| **Used For...** | Consolidating time slots, finding free time. | Adding appointments, dynamic scheduling. |
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Understanding the Cyclic Sort Concept
2+
3+
Think of Cyclic Sort like a group of people holding numbered tickets (from 1 to N) standing in a row of chairs, but they are completely scrambled. To fix this, you tell the first person to go to the chair that matches their ticket. They swap places with whoever is sitting there. You repeat this until the person in the first chair actually has ticket number 1. Then you move to the second chair and do the same.
4+
5+
This pattern is highly effective when you are dealing with an array containing numbers in a given range (e.g., 1 to N, or 0 to N). Because the numbers match the array indices, we can place them at their correct index in O(N) time without using traditional O(N log N) sorting algorithms.
6+
7+
There are two primary variations:
8+
1. **Finding the Missing Number**.
9+
2. **Finding the Duplicate Number**.
10+
11+
## Type 1: Placing Numbers in Correct Indices
12+
We iterate through the array. For each number, if it is not at its correct index (i.e., `number != array[number - 1]`), we swap it with the number that is currently at its correct index.
13+
14+
### The Process Step-by-Step
15+
**Goal:** Sort the array `[3, 1, 5, 4, 2]` containing numbers 1 to 5.
16+
17+
```plaintext
18+
Indices: 0 1 2 3 4
19+
Data: [3, 1, 5, 4, 2]
20+
21+
Step 1: Index 0 has '3'. Correct index for '3' is 2. Swap(0, 2)
22+
Data becomes: [5, 1, 3, 4, 2]
23+
24+
Step 2: Index 0 has '5'. Correct index for '5' is 4. Swap(0, 4)
25+
Data becomes: [2, 1, 3, 4, 5]
26+
27+
Step 3: Index 0 has '2'. Correct index for '2' is 1. Swap(0, 1)
28+
Data becomes: [1, 2, 3, 4, 5]
29+
30+
Step 4: Index 0 has '1'. Correct index. Move to Index 1.
31+
Step 5: Index 1 has '2'. Correct index. Move to Index 2.
32+
Step 6: Index 2 has '3'. Correct index. Move to Index 3.
33+
... (All are in correct places).
34+
```
35+
36+
## Type 2: Finding Missing or Duplicate Numbers
37+
Once the array is cyclically sorted, finding missing or duplicate numbers is trivial. We just iterate through the sorted array, and the first index that doesn't match its expected value holds the duplicate (and the missing number is the expected value of that index).
38+
39+
### The Process Step-by-Step
40+
**Goal:** Find the missing number in `[4, 2, 1, 4]` (range 1 to 4).
41+
42+
```plaintext
43+
Indices: 0 1 2 3
44+
Data: [4, 2, 1, 4]
45+
46+
Step 1: Index 0 has '4'. Correct index for '4' is 3. Swap(0, 3)
47+
Data becomes: [4, 2, 1, 4] <- Wait, index 3 already has a '4'. Duplicate found!
48+
Move to next index.
49+
50+
Step 2: Index 1 has '2'. Correct index. Move to Index 2.
51+
Step 3: Index 2 has '1'. Correct index for '1' is 0. Swap(2, 0)
52+
Data becomes: [1, 2, 4, 4]
53+
54+
Step 4: Array is cyclically sorted as much as possible.
55+
Let's scan:
56+
Index 0: 1 (Matches)
57+
Index 1: 2 (Matches)
58+
Index 2: 4 (Mismatch! Should be 3. Missing is 3, Duplicate is 4)
59+
```
60+
61+
### Comparison Summary
62+
| Feature | Missing Number | Duplicate Number |
63+
|---------|----------------|------------------|
64+
| **Core Action** | Swap numbers to target indices. | Swap numbers to target indices. |
65+
| **Detection Phase** | Scan for `array[i] != i + 1` | Same, or stop when `array[current] == array[target]` |
66+
| **Used For...** | Ranges 0 to N or 1 to N, finding missing numbers. | Finding single or multiple duplicates in O(N) time and O(1) space. |
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Understanding In-Place Reversal of a LinkedList
2+
3+
Think of reversing a LinkedList like turning a series of one-way street signs to point in the opposite direction. You start at the first sign, turn it to point behind you, move to the next sign, turn it to point to the previous one, and so on. You don't need to build a whole new road of signs; you just change where the current ones point.
4+
5+
In code, this means we reverse the pointers of a LinkedList without using any extra memory. We rely on three pointers: `Current`, `Previous`, and `Next`.
6+
7+
There are two primary types:
8+
1. **Reversing the Entire List**.
9+
2. **Reversing a Sub-list (a specific portion)**.
10+
11+
## Type 1: Reversing the Entire List
12+
We iterate through the list. At each node, we save the next node, reverse the current node's pointer to point to the previous node, and then shift our pointers one step forward.
13+
14+
### The Process Step-by-Step
15+
**Goal:** Reverse the linked list `1 -> 2 -> 3 -> null`.
16+
17+
```plaintext
18+
Setup: Prev = null, Current = 1
19+
20+
Step 1: [Current: 1]
21+
Next = 1.next (which is 2)
22+
1.next = Prev (which is null, so 1 -> null)
23+
Prev = 1
24+
Current = 2
25+
(List state: 1 -> null. Remaining: 2 -> 3 -> null)
26+
27+
Step 2: [Current: 2]
28+
Next = 2.next (which is 3)
29+
2.next = Prev (which is 1, so 2 -> 1 -> null)
30+
Prev = 2
31+
Current = 3
32+
(List state: 2 -> 1 -> null. Remaining: 3 -> null)
33+
34+
Step 3: [Current: 3]
35+
Next = 3.next (which is null)
36+
3.next = Prev (which is 2, so 3 -> 2 -> 1 -> null)
37+
Prev = 3
38+
Current = null
39+
40+
Result: Current is null, loop ends. Head is now Prev (3).
41+
Final list: 3 -> 2 -> 1 -> null.
42+
```
43+
44+
## Type 2: Reversing a Sub-list
45+
If we only want to reverse from position `p` to `q`, we skip the first `p-1` nodes. We remember the node right before `p` (to connect it later to the new head of the reversed part) and remember the `p`th node itself (which will become the tail and needs to connect to `q+1`).
46+
47+
### The Process Step-by-Step
48+
**Goal:** Reverse positions 2 to 4 in `1 -> 2 -> 3 -> 4 -> 5 -> null`.
49+
50+
```plaintext
51+
Step 1: Skip to position p (node 2).
52+
Node before p is '1' (let's call it nodeBeforeSublist).
53+
Node at p is '2' (let's call it sublistWorkingTail).
54+
55+
Step 2: Reverse nodes from position 2 to 4.
56+
Reverse 2, 3, 4 just like Type 1.
57+
Reversed sublist becomes: 4 -> 3 -> 2 -> null.
58+
59+
Step 3: Reconnect.
60+
nodeBeforeSublist.next = reversedHead (1 -> 4 -> 3 -> 2)
61+
sublistWorkingTail.next = nodeAfterSublist (2 -> 5)
62+
63+
Result: 1 -> 4 -> 3 -> 2 -> 5 -> null
64+
```
65+
66+
### Comparison Summary
67+
| Feature | Entire List | Sub-list |
68+
|---------|-------------|----------|
69+
| **Traversal** | Starts from Head to end. | Skips to `p`, reverses to `q`, stops. |
70+
| **Pointers Needed** | `Prev`, `Current`, `Next` | `Prev`, `Current`, `Next` + references to reconnect bounds. |
71+
| **Complexity** | O(N) time, O(1) space. | O(N) time, O(1) space. |
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Understanding Tree Breadth-First Search (BFS)
2+
3+
Think of Tree BFS like exploring a corporate hierarchy level by level. You start at the top (the CEO). Before talking to any managers, you talk to all the Vice Presidents (level 1). Then, you talk to all the Directors (level 2), and finally the Managers (level 3). You never skip a level.
4+
5+
To keep track of who to talk to next without jumping ahead, we use a **Queue** (a First-In-First-Out line, like people waiting at a grocery store).
6+
7+
There are two primary variations:
8+
1. **Standard Level Order Traversal** (Left-to-Right).
9+
2. **Zigzag Traversal** (Alternating directions per level).
10+
11+
## Type 1: Standard Level Order Traversal
12+
We push the root node into the queue. Then, we use a loop that runs as long as the queue has elements. Inside the loop, we count how many nodes are in the queue (this is the size of the current level), pop that many nodes, and push their children into the queue for the next level.
13+
14+
### The Process Step-by-Step
15+
**Goal:** Traverse the tree level by level.
16+
Tree:
17+
1
18+
/ \
19+
2 3
20+
/ \ / \
21+
4 5 6 7
22+
23+
```plaintext
24+
Step 1: Initialize Queue = [1]
25+
Result = []
26+
27+
Step 2: Queue size is 1 (Level 0).
28+
Pop 1. Add 1 to Result.
29+
Push children of 1 (2, 3).
30+
Queue = [2, 3]
31+
Result = [[1]]
32+
33+
Step 3: Queue size is 2 (Level 1).
34+
Pop 2. Add to levelResult. Push children (4, 5).
35+
Pop 3. Add to levelResult. Push children (6, 7).
36+
Queue = [4, 5, 6, 7]
37+
Result = [[1], [2, 3]]
38+
39+
Step 4: Queue size is 4 (Level 2).
40+
Pop 4, 5, 6, 7. Push their children (none).
41+
Queue = []
42+
Result = [[1], [2, 3], [4, 5, 6, 7]]
43+
```
44+
45+
## Type 2: Zigzag Traversal
46+
This is exactly the same as standard BFS, but we maintain a boolean flag that flips at each level. If the flag is true, we add the popped nodes to the current level's result array from left-to-right. If false, we add them right-to-left.
47+
48+
### The Process Step-by-Step
49+
**Goal:** Zigzag traverse the same tree.
50+
51+
```plaintext
52+
Step 1: Level 0 (Left-to-Right).
53+
Queue = [1]. Pop 1.
54+
Level Result = [1].
55+
Push children (2, 3). Queue = [2, 3]
56+
57+
Step 2: Level 1 (Right-to-Left).
58+
Queue size = 2.
59+
Pop 2. Insert at BEGINNING of Level Result -> [2].
60+
Pop 3. Insert at BEGINNING of Level Result -> [3, 2].
61+
Push children (4, 5, 6, 7). Queue = [4, 5, 6, 7]
62+
63+
Step 3: Level 2 (Left-to-Right).
64+
Queue size = 4.
65+
Pop 4, 5, 6, 7. Append normally.
66+
Level Result = [4, 5, 6, 7].
67+
68+
Result: [[1], [3, 2], [4, 5, 6, 7]]
69+
```
70+
71+
### Comparison Summary
72+
| Feature | Standard Level Order | Zigzag Traversal |
73+
|---------|----------------------|------------------|
74+
| **Data Structure** | Queue | Queue (with directional flag) |
75+
| **Collection Method**| Append to end of level list. | Alternate append to end / insert at front. |
76+
| **Used For...** | Shortest path, level averages, right-view. | Specialized UI rendering, spiral matrix logic. |

0 commit comments

Comments
 (0)