Skip to content

Commit b0483fd

Browse files
committed
Updates
1 parent 3b6a0fd commit b0483fd

12 files changed

+310
-47
lines changed

asset-manifest.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"files": {
3-
"main.css": "/static/css/main.e49c5249.css",
4-
"main.js": "/static/js/main.75bc386a.js",
3+
"main.css": "/static/css/main.48dcc016.css",
4+
"main.js": "/static/js/main.4a3e41b2.js",
55
"static/js/453.f568ff1d.chunk.js": "/static/js/453.f568ff1d.chunk.js",
66
"static/media/border.jpg": "/static/media/border.b7869a9ea7ccd009873c.jpg",
77
"static/media/parchment.png": "/static/media/parchment.c4af92656f29dc66bd67.png",
@@ -10,12 +10,12 @@
1010
"static/media/slick.ttf": "/static/media/slick.c94f7671dcc99dce43e2.ttf",
1111
"static/media/slick.woff": "/static/media/slick.295183786cd8a1389865.woff",
1212
"index.html": "/index.html",
13-
"main.e49c5249.css.map": "/static/css/main.e49c5249.css.map",
14-
"main.75bc386a.js.map": "/static/js/main.75bc386a.js.map",
13+
"main.48dcc016.css.map": "/static/css/main.48dcc016.css.map",
14+
"main.4a3e41b2.js.map": "/static/js/main.4a3e41b2.js.map",
1515
"453.f568ff1d.chunk.js.map": "/static/js/453.f568ff1d.chunk.js.map"
1616
},
1717
"entrypoints": [
18-
"static/css/main.e49c5249.css",
19-
"static/js/main.75bc386a.js"
18+
"static/css/main.48dcc016.css",
19+
"static/js/main.4a3e41b2.js"
2020
]
2121
}

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<!doctype html><html lang="en" class="dark"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><link rel="icon" type="image/svg+xml" href="/favicon.svg"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><link rel="alternate" type="application/rss+xml" title="Fezcodex RSS Feed" href="/rss.xml"/><meta name="description" content="codex by fezcode..."/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Space+Mono:wght@400;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Arvo&family=Inter&family=Playfair+Display&display=swap" rel="stylesheet"><title>fezcodex</title><script defer="defer" src="/static/js/main.75bc386a.js"></script><link href="/static/css/main.e49c5249.css" rel="stylesheet"></head><body class="bg-slate-950"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
1+
<!doctype html><html lang="en" class="dark"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><link rel="icon" type="image/svg+xml" href="/favicon.svg"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><link rel="alternate" type="application/rss+xml" title="Fezcodex RSS Feed" href="/rss.xml"/><meta name="description" content="codex by fezcode..."/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Space+Mono:wght@400;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Arvo&family=Inter&family=Playfair+Display&display=swap" rel="stylesheet"><title>fezcodex</title><script defer="defer" src="/static/js/main.4a3e41b2.js"></script><link href="/static/css/main.48dcc016.css" rel="stylesheet"></head><body class="bg-slate-950"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
2+
# Understanding Trees, Binary Search Trees, and Finding the Lowest Common Ancestor
3+
4+
In the world of computer science, data structures are the building blocks of efficient algorithms. One of the most fundamental and versatile data structures is the **Tree**.
5+
6+
This post will take you on a journey from the basics of trees to a specific type called a Binary Search Tree (BST), explore common algorithms used with them, and finally, solve a classic problem: finding the Lowest Common Ancestor of two nodes in a BST.
7+
8+
## What is a Tree?
9+
10+
In computer science, a **Tree** is a hierarchical data structure that consists of nodes connected by edges.
11+
12+
Unlike linear data structures like arrays or linked lists, trees are non-linear and are used to represent hierarchical relationships.
13+
14+
### Key Terminology:
15+
16+
* **Node:** The fundamental part of a tree that stores data.
17+
* **Edge:** The connection between two nodes.
18+
* **Root:** The topmost node in a tree. It's the only node that doesn't have a parent.
19+
* **Parent:** A node that has a child node.
20+
* **Child:** A node that has a parent node.
21+
* **Leaf:** A node that does not have any children.
22+
* **Subtree:** A tree consisting of a node and its descendants.
23+
* **Depth:** The length of the path from the root to a specific node.
24+
* **Height:** The length of the longest path from a specific node to a leaf.
25+
26+
Trees are used in various applications, such as file systems, organization charts, and even in parsing expressions in compilers.
27+
28+
## Binary Search Trees (BSTs)
29+
30+
A **Binary Search Tree (BST)** is a special type of binary tree where the nodes are ordered in a specific way.
31+
32+
This ordering makes operations like searching, insertion, and deletion very efficient.
33+
34+
A binary tree is a BST if it satisfies the following properties:
35+
36+
1. The left subtree of a node contains only nodes with keys **lesser** than the node's key.
37+
2. The right subtree of a node contains only nodes with keys **greater** than the node's key.
38+
3. Both the left and right subtrees must also be binary search trees.
39+
40+
This structure ensures that for any given node, all the values in its left subtree are smaller, and all the values in its right subtree are larger.
41+
42+
## Common Tree Algorithms
43+
44+
Trees have a variety of algorithms for traversal and manipulation. The most common are traversal algorithms, which visit each node in the tree exactly once.
45+
46+
### Tree Traversal
47+
48+
There are two main approaches to traversing a tree:
49+
50+
1. **Depth-First Search (DFS):** This approach explores as far as possible down one branch before backtracking. There are three common ways to perform DFS:
51+
* **In-order Traversal:** Visit the left subtree, then the root, then the right subtree. For a BST, this traversal visits the nodes in ascending order.
52+
* **Pre-order Traversal:** Visit the root, then the left subtree, then the right subtree. This is useful for creating a copy of the tree.
53+
* **Post-order Traversal:** Visit the left subtree, then the right subtree, then the root. This is useful for deleting nodes from the tree.
54+
55+
2. **Breadth-First Search (BFS):** This approach explores the tree level by level. It visits all the nodes at a given depth before moving on to the next level. BFS is typically implemented using a queue.
56+
57+
## More Tree Algorithms in Go
58+
59+
Let's explore how to implement some of these fundamental tree algorithms in Go.
60+
61+
### Finding the Height/Depth of a Binary Tree
62+
63+
The **height** of a binary tree is the number of edges on the longest path from the root node to a leaf node. A tree with only a root node has a height of 0.
64+
65+
The concept is closely related to the **depth** of a node, which is its distance from the root. The height of the tree is, therefore, the maximum depth of any node in the tree.
66+
67+
We can calculate the height recursively. The height of a node is 1 plus the maximum height of its left or right subtree.
68+
69+
```go
70+
import "math"
71+
72+
// TreeNode definition from before
73+
type TreeNode struct {
74+
Val int
75+
Left *TreeNode
76+
Right *TreeNode
77+
}
78+
79+
func max(a, b int) int {
80+
if a > b {
81+
return a
82+
}
83+
return b
84+
}
85+
86+
func height(node *TreeNode) int {
87+
if node == nil {
88+
return -1 // Height of a null tree is -1
89+
}
90+
leftHeight := height(node.Left)
91+
rightHeight := height(node.Right)
92+
return 1 + max(leftHeight, rightHeight)
93+
}
94+
```
95+
96+
### DFS Traversals in Go
97+
98+
Here are the Go implementations for the three DFS traversal methods.
99+
100+
#### In-order Traversal
101+
102+
```go
103+
func inOrderTraversal(node *TreeNode) {
104+
if node == nil {
105+
return
106+
}
107+
inOrderTraversal(node.Left)
108+
fmt.Println(node.Val) // Process the node
109+
inOrderTraversal(node.Right)
110+
}
111+
```
112+
113+
#### Pre-order Traversal
114+
115+
```go
116+
func preOrderTraversal(node *TreeNode) {
117+
if node == nil {
118+
return
119+
}
120+
fmt.Println(node.Val) // Process the node
121+
preOrderTraversal(node.Left)
122+
preOrderTraversal(node.Right)
123+
}
124+
```
125+
126+
#### Post-order Traversal
127+
128+
```go
129+
func postOrderTraversal(node *TreeNode) {
130+
if node == nil {
131+
return
132+
}
133+
postOrderTraversal(node.Left)
134+
postOrderTraversal(node.Right)
135+
fmt.Println(node.Val) // Process the node
136+
}
137+
```
138+
139+
## LeetCode 235: Lowest Common Ancestor of a Binary Search Tree
140+
141+
Now, let's apply our knowledge to a classic problem.
142+
143+
The **Lowest Common Ancestor (LCA)** of two nodes, `p` and `q`, in a tree is the lowest (i.e., deepest) node that has both `p` and `q` as descendants.
144+
145+
### The Problem
146+
147+
Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.
148+
149+
For example, consider the following BST:
150+
151+
```
152+
6
153+
/ \
154+
2 8
155+
/ \ / \
156+
0 4 7 9
157+
/ \
158+
3 5
159+
```
160+
161+
* The LCA of nodes `2` and `8` is `6`.
162+
* The LCA of nodes `2` and `4` is `2`, since a node can be a descendant of itself.
163+
* The LCA of nodes `3` and `5` is `4`.
164+
165+
166+
### The Solution
167+
168+
The properties of a BST make finding the LCA particularly efficient.
169+
170+
We can start at the root of the tree and use the values of `p` and `q` to decide where to go next.
171+
172+
Let's consider the current node we are at, let's call it `current`.
173+
174+
1. If both `p` and `q` are **greater** than `current.val`, it means that the LCA must be in the **right** subtree. So, we move to the right child.
175+
2. If both `p` and `q` are **less** than `current.val`, it means that the LCA must be in the **left** subtree. So, we move to the left child.
176+
3. If one of `p` or `q` is greater than `current.val` and the other is less than `current.val` (or if one of them is equal to `current.val`), then `current` is the LCA.
177+
178+
This is because `p` and `q` are on opposite sides of the current node, meaning it's the split point and thus the lowest common ancestor.
179+
180+
We can implement this logic both iteratively and recursively.
181+
182+
### Iterative Solution
183+
184+
```go
185+
/**
186+
* Definition for a binary tree node.
187+
* type TreeNode struct {
188+
* Val int
189+
* Left *TreeNode
190+
* Right *TreeNode
191+
* }
192+
*/
193+
194+
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
195+
current := root
196+
for current != nil {
197+
if p.Val > current.Val && q.Val > current.Val {
198+
current = current.Right
199+
} else if p.Val < current.Val && q.Val < current.Val {
200+
current = current.Left
201+
} else {
202+
return current
203+
}
204+
}
205+
return nil // Should not be reached in a valid BST
206+
}
207+
```
208+
209+
### Recursive Solution
210+
211+
```go
212+
/**
213+
* Definition for a binary tree node.
214+
* type TreeNode struct {
215+
* Val int
216+
* Left *TreeNode
217+
* Right *TreeNode
218+
* }
219+
*/
220+
221+
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
222+
if root == nil {
223+
return nil
224+
}
225+
226+
if p.Val > root.Val && q.Val > root.Val {
227+
return lowestCommonAncestor(root.Right, p, q)
228+
} else if p.Val < root.Val && q.Val < root.Val {
229+
return lowestCommonAncestor(root.Left, p, q)
230+
} else {
231+
return root
232+
}
233+
}
234+
```
235+
236+
Both of these solutions are very efficient, with a time complexity of O(H), where H is the height of the tree. In a balanced BST, this is O(log N), where N is the number of nodes.
237+
238+
The space complexity for the iterative solution is O(1), while the recursive solution has a space complexity of O(H) due to the call stack.
239+
240+
## Conclusion
241+
242+
Trees and Binary Search Trees are powerful data structures that are essential for any programmer's toolkit. By understanding their properties and the algorithms that operate on them, you can solve a wide range of problems efficiently.
243+
244+
The Lowest Common Ancestor problem is a perfect example of how the structure of a BST can be leveraged to find an elegant and optimal solution.

posts/posts.json

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,4 @@
11
[
2-
{
3-
"slug": "algos",
4-
"title": "Algorithms",
5-
"date": "2025-11-04",
6-
"description": "Algorithms",
7-
"tags": ["cs", "algorithms", "graphs"],
8-
"series": {
9-
"posts": [
10-
{
11-
"slug": "monotonic-stack",
12-
"title": "Monotonic Stack with Daily Temperatures",
13-
"date": "2025-11-05",
14-
"description": "Monotonic Stack with Daily Temperatures",
15-
"tags": ["cs", "algorithms", "stack", "monotonic-stack"],
16-
"category": "dev",
17-
"filename": "/algos/monotonic-stack.txt"
18-
},
19-
{
20-
"slug": "wquwpc",
21-
"title": "Weighted Quick-Union with Path Compression",
22-
"date": "2025-11-04",
23-
"description": "Weighted Quick-Union with Path Compression",
24-
"tags": ["cs", "algorithms", "graphs"],
25-
"category": "dev",
26-
"filename": "/algos/weighted-quick-union-with-path-compression.txt"
27-
}
28-
]
29-
}
30-
},
312
{
323
"slug": "ubuntu-once-more",
334
"title": "Ubuntu Once More",
@@ -243,5 +214,43 @@
243214
"tags": ["writing", "updates"],
244215
"category": "rant",
245216
"filename": "about-fezcodex.txt"
217+
},
218+
{
219+
"slug": "algos",
220+
"title": "Algorithms",
221+
"date": "2025-10-01",
222+
"description": "Algorithms",
223+
"tags": ["cs", "algorithms", "graphs"],
224+
"series": {
225+
"posts": [
226+
{
227+
"slug": "lca",
228+
"title": "Lowest Common Ancestor with Binary Search Tree",
229+
"date": "2025-11-07",
230+
"description": "Lowest Common Ancestor with Binary Search Tree",
231+
"tags": ["cs", "algorithms", "tree", "bst", "recursion", "iterative"],
232+
"category": "dev",
233+
"filename": "/algos/lowest-common-ancestor-of-a-binary-search-tree.txt"
234+
},
235+
{
236+
"slug": "monotonic-stack",
237+
"title": "Monotonic Stack with Daily Temperatures",
238+
"date": "2025-11-05",
239+
"description": "Monotonic Stack with Daily Temperatures",
240+
"tags": ["cs", "algorithms", "stack", "monotonic-stack"],
241+
"category": "dev",
242+
"filename": "/algos/monotonic-stack.txt"
243+
},
244+
{
245+
"slug": "wquwpc",
246+
"title": "Weighted Quick-Union with Path Compression",
247+
"date": "2025-11-04",
248+
"description": "Weighted Quick-Union with Path Compression",
249+
"tags": ["cs", "algorithms", "graphs"],
250+
"category": "dev",
251+
"filename": "/algos/weighted-quick-union-with-path-compression.txt"
252+
}
253+
]
254+
}
246255
}
247256
]

rss.xml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,24 @@
99
<link>https://fezcode.com</link>
1010
</image>
1111
<generator>RSS for Node</generator>
12-
<lastBuildDate>Tue, 04 Nov 2025 22:07:04 GMT</lastBuildDate>
12+
<lastBuildDate>Thu, 06 Nov 2025 22:37:00 GMT</lastBuildDate>
1313
<atom:link href="https://fezcode.com/rss.xml" rel="self" type="application/rss+xml"/>
14-
<pubDate>Tue, 04 Nov 2025 22:07:04 GMT</pubDate>
14+
<pubDate>Thu, 06 Nov 2025 22:37:00 GMT</pubDate>
1515
<copyright><![CDATA[2025 Ahmed Samil Bulbul]]></copyright>
1616
<language><![CDATA[en]]></language>
1717
<managingEditor><![CDATA[samil.bulbul@gmail.com (Ahmed Samil Bulbul)]]></managingEditor>
1818
<webMaster><![CDATA[samil.bulbul@gmail.com (Ahmed Samil Bulbul)]]></webMaster>
1919
<ttl>60</ttl>
20+
<item>
21+
<title><![CDATA[Lowest Common Ancestor with Binary Search Tree]]></title>
22+
<description><![CDATA[[object Object]]]></description>
23+
<link>https://fezcode.com/#/blog/lca</link>
24+
<guid isPermaLink="false">https://fezcode.com/#/blog/lca</guid>
25+
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
26+
<pubDate>Fri, 07 Nov 2025 00:00:00 GMT</pubDate>
27+
<content:encoded><![CDATA[<h1>Understanding Trees, Binary Search Trees, and Finding the Lowest Common Ancestor</h1>
28+
<p><a href="https://fezcode.com/#/blog/lca">Read more...</a></p>]]></content:encoded>
29+
</item>
2030
<item>
2131
<title><![CDATA[Monotonic Stack with Daily Temperatures]]></title>
2232
<description><![CDATA[[object Object]]]></description>

static/css/main.48dcc016.css

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

static/css/main.48dcc016.css.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

static/css/main.e49c5249.css

Lines changed: 0 additions & 4 deletions
This file was deleted.

static/css/main.e49c5249.css.map

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)