@@ -2,156 +2,273 @@ Tree: Breadth-First Search (BFS)
2
2
================================
3
3
4
4
- Introduction:
5
+ ===============
5
6
6
- Breadth-First Search (BFS) is a fundamental algorithm used for traversing or searching tree or graph data structures.
7
- It starts at the root (or any arbitrary node in the case of a graph) and explores all the neighboring nodes at the
8
- present depth before moving on to nodes at the next depth level. This process continues until all nodes are visited
9
- or a specific condition is met (e.g., finding a particular node).
7
+ Breadth-First Search (BFS) is a fundamental algorithm used for traversing or searching tree or graph data structures.
8
+ It starts at the root (or any arbitrary node in the case of a graph) and explores all the neighboring nodes at the
9
+ present depth before moving on to nodes at the next depth level. This process continues until all nodes are visited
10
+ or a specific condition is met (e.g., finding a particular node).
10
11
11
- Here is a step-by-step explanation of the BFS algorithm:
12
+ - Here is a step-by-step explanation of the BFS algorithm:
13
+ ===========================================================
12
14
13
- 1. Initialization:
14
- - Begin by placing the root node (or the starting node) in a queue.
15
- - Mark this node as visited.
15
+ 1. Initialization:
16
+ ------------------
16
17
17
- 2. Traversal:
18
- - While the queue is not empty:
19
- - Remove the front node from the queue.
20
- - Process this node (e.g., visit or print the node's value).
21
- - Add all unvisited neighboring nodes (or children, in the case of a tree) of the current node to the queue and mark them as visited.
18
+ - Begin by placing the root node (or the starting node) in a queue.
19
+ - Mark this node as visited.
22
20
23
- 3. Termination :
24
- - The algorithm terminates when the queue becomes empty, meaning all reachable nodes have been visited.
21
+ 2. Traversal :
22
+ -------------
25
23
26
- Example in a Tree
24
+ - While the queue is not empty:
25
+ - Remove the front node from the queue.
26
+ - Process this node (e.g., visit or print the node's value).
27
+ - Add all unvisited neighboring nodes (or children, in the case of a tree) of the current node to the queue and mark them as visited.
27
28
28
- Let's consider a simple tree:
29
+ 3. Termination:
30
+ ---------------
29
31
30
- A
31
- / \
32
- B C
33
- / \ \
34
- D E F
32
+ - The algorithm terminates when the queue becomes empty, meaning all reachable nodes have been visited.
35
33
36
- BFS Traversal:
37
- 1. Start at the root node `A` and add it to the queue: `Queue = [A]`
38
- 2. Dequeue `A` and visit it, then enqueue its children `B` and `C`: `Queue = [B, C]`
39
- 3. Dequeue `B` and visit it, then enqueue its children `D` and `E`: `Queue = [C, D, E]`
40
- 4. Dequeue `C` and visit it, then enqueue its child `F`: `Queue = [D, E, F]`
41
- 5. Dequeue `D` and visit it: `Queue = [E, F]`
42
- 6. Dequeue `E` and visit it: `Queue = [F]`
43
- 7. Dequeue `F` and visit it: `Queue = []`
34
+ * Example in a Tree
44
35
45
- The BFS traversal order for this tree is: `A -> B -> C -> D -> E -> F`.
36
+ Let's consider a simple tree:
46
37
47
- BFS Algorithm in Pseudocode
38
+ A
39
+ / \
40
+ B C
41
+ / \ \
42
+ D E F
48
43
49
- Here is the BFS algorithm in pseudocode for a tree:
44
+ 4. BFS Traversal:
45
+ -----------------
50
46
51
- BFS(root):
52
- queue = empty queue
53
- queue.enqueue(root)
54
- visited = set()
55
- visited.add(root)
47
+ 1. Start at the root node `A` and add it to the queue: `Queue = [A]`
48
+ 2. Dequeue `A` and visit it, then enqueue its children `B` and `C`: `Queue = [B, C]`
49
+ 3. Dequeue `B` and visit it, then enqueue its children `D` and `E`: `Queue = [C, D, E]`
50
+ 4. Dequeue `C` and visit it, then enqueue its child `F`: `Queue = [D, E, F]`
51
+ 5. Dequeue `D` and visit it: `Queue = [E, F]`
52
+ 6. Dequeue `E` and visit it: `Queue = [F]`
53
+ 7. Dequeue `F` and visit it: `Queue = []`
56
54
57
- while not queue.isEmpty():
58
- node = queue.dequeue()
59
- visit(node)
55
+ The BFS traversal order for this tree is: `A -> B -> C -> D -> E -> F`.
60
56
61
- for each child in node.children:
62
- if child not in visited:
63
- queue.enqueue(child)
64
- visited.add(child)
57
+ * BFS Algorithm in Pseudocode
65
58
66
- Characteristics of BFS
59
+ Here is the BFS algorithm in pseudocode for a tree:
67
60
68
- - Complete: BFS will find a solution if one exists.
69
- - Optimal: BFS will find the shortest path in an unweighted graph or tree.
70
- - Time Complexity: O(V + E) where V is the number of vertices (nodes) and E is the number of edges.
71
- - Space Complexity: O(V) because of the queue and the visited set.
61
+ BFS(root):
62
+ queue = empty queue
63
+ queue.enqueue(root)
64
+ visited = set()
65
+ visited.add(root)
72
66
73
- Applications of BFS
67
+ while not queue.isEmpty():
68
+ node = queue.dequeue()
69
+ visit(node)
74
70
75
- - Finding the shortest path in an unweighted graph.
76
- - Level-order traversal of a tree.
77
- - Networking (broadcasting and peer-to-peer networks).
78
- - Finding connected components in a graph.
79
- - Solving puzzles (like finding the shortest path to a goal state in a puzzle).
71
+ for each child in node.children:
72
+ if child not in visited:
73
+ queue.enqueue(child)
74
+ visited.add(child)
80
75
81
- Tree level-order traversal is a variant of the Breadth-First Search (BFS) algorithm.
76
+ * Characteristics of BFS
82
77
83
- Tree level-order traversal, also known as Breadth-First Search (BFS) traversal, is a method of visiting all the nodes
84
- in a tree level by level, starting from the root and proceeding to the next level down, visiting nodes from left to right at each level.
78
+ - Complete: BFS will find a solution if one exists.
79
+ - Optimal: BFS will find the shortest path in an unweighted graph or tree.
80
+ - Time Complexity: O(V + E) where V is the number of vertices (nodes) and E is the number of edges.
81
+ - Space Complexity: O(V) because of the queue and the visited set.
85
82
86
- How Level Order Traversal Works
83
+ * Applications of BFS
87
84
88
- 1. Initialization:
89
- - Start by placing the root node of the tree in a queue.
85
+ - Finding the shortest path in an unweighted graph.
86
+ - Level-order traversal of a tree.
87
+ - Networking (broadcasting and peer-to-peer networks).
88
+ - Finding connected components in a graph.
89
+ - Solving puzzles (like finding the shortest path to a goal state in a puzzle).
90
90
91
- 2. Traversal:
92
- - While the queue is not empty:
93
- - Dequeue the front node from the queue.
94
- - Process the node (e.g., print its value).
95
- - Enqueue all the children (or left and right child for binary trees) of the dequeued node.
91
+ 5. Tree level-order traversal is a variant of the Breadth-First Search (BFS) algorithm.
92
+ ----------------------------------------------------------------------------------------
96
93
97
- 3. Termination:
98
- - The traversal is complete when the queue is empty, meaning all nodes have been visited .
94
+ Tree level-order traversal, also known as Breadth-First Search (BFS) traversal, is a method of visiting all the nodes
95
+ in a tree level by level, starting from the root and proceeding to the next level down, visiting nodes from left to right at each level .
99
96
100
- Example
97
+ * How Level Order Traversal Works
101
98
102
- Consider the following binary tree:
99
+ 1. Initialization:
100
+ - Start by placing the root node of the tree in a queue.
103
101
104
- A
105
- / \
106
- B C
107
- / \ \
108
- D E F
102
+ 2. Traversal:
103
+ - While the queue is not empty:
104
+ - Dequeue the front node from the queue.
105
+ - Process the node (e.g., print its value).
106
+ - Enqueue all the children (or left and right child for binary trees) of the dequeued node.
109
107
110
- Level Order Traversal steps:
111
- 1. Start at the root node `A` and add it to the queue: `Queue = [A]`
112
- 2. Dequeue `A` and visit it, then enqueue its children `B` and `C`: `Queue = [B, C]`
113
- 3. Dequeue `B` and visit it, then enqueue its children `D` and `E`: `Queue = [C, D, E]`
114
- 4. Dequeue `C` and visit it, then enqueue its child `F`: `Queue = [D, E, F]`
115
- 5. Dequeue `D` and visit it: `Queue = [E, F]`
116
- 6. Dequeue `E` and visit it: `Queue = [F]`
117
- 7. Dequeue `F` and visit it: `Queue = []`
108
+ 3. Termination:
109
+ - The traversal is complete when the queue is empty, meaning all nodes have been visited.
118
110
119
- Level Order Traversal Order: `A -> B -> C -> D -> E -> F`
111
+ * Example
120
112
121
- Pseudocode
113
+ Consider the following binary tree:
122
114
123
- Here is the pseudocode for level-order traversal:
115
+ A
116
+ / \
117
+ B C
118
+ / \ \
119
+ D E F
124
120
125
- LevelOrderTraversal(root):
126
- if root is None:
127
- return
121
+ Level Order Traversal steps:
122
+ 1. Start at the root node `A` and add it to the queue: `Queue = [A]`
123
+ 2. Dequeue `A` and visit it, then enqueue its children `B` and `C`: `Queue = [B, C]`
124
+ 3. Dequeue `B` and visit it, then enqueue its children `D` and `E`: `Queue = [C, D, E]`
125
+ 4. Dequeue `C` and visit it, then enqueue its child `F`: `Queue = [D, E, F]`
126
+ 5. Dequeue `D` and visit it: `Queue = [E, F]`
127
+ 6. Dequeue `E` and visit it: `Queue = [F]`
128
+ 7. Dequeue `F` and visit it: `Queue = []`
128
129
129
- queue = empty queue
130
- queue.enqueue(root)
130
+ Level Order Traversal Order: `A -> B -> C -> D -> E -> F`
131
131
132
- while not queue.isEmpty():
133
- node = queue.dequeue()
134
- visit(node) // Process the node, e.g., print its value
132
+ * Pseudocode
135
133
136
- if node.left is not None:
137
- queue.enqueue(node.left)
134
+ Here is the pseudocode for level-order traversal:
138
135
139
- if node.right is not None:
140
- queue.enqueue(node.right)
136
+ LevelOrderTraversal(root):
137
+ if root is None:
138
+ return
141
139
142
- Characteristics
140
+ queue = empty queue
141
+ queue.enqueue(root)
143
142
144
- - Complete: Level-order traversal will visit all nodes in the tree.
145
- - Optimal: Not applicable for optimization but ensures all nodes are visited in level order.
146
- - Time Complexity: O(N) where N is the number of nodes in the tree, since each node is enqueued and dequeued exactly once.
147
- - Space Complexity: O(N) in the worst case, where the last level of the tree might have up to N/2 nodes.
143
+ while not queue.isEmpty():
144
+ node = queue.dequeue()
145
+ visit(node) // Process the node, e.g., print its value
148
146
149
- Applications
147
+ if node.left is not None:
148
+ queue.enqueue(node.left)
150
149
151
- - Shortest Path in Unweighted Graphs: BFS can be used to find the shortest path in an unweighted graph.
152
- - Level-Order Display: Useful for printing the tree level by level.
153
- - Serialization/Deserialization of Trees: Often used in algorithms that serialize and deserialize trees.
154
- - Breadth of Trees: Can be used to calculate the breadth (width) of the tree at different levels.
150
+ if node.right is not None:
151
+ queue.enqueue(node.right)
155
152
156
- In summary, level-order traversal (BFS) is an important method for tree traversal that processes nodes level by level,
157
- ensuring that all nodes at a given level are visited before moving on to the next level.
153
+ * Characteristics
154
+
155
+ - Complete: Level-order traversal will visit all nodes in the tree.
156
+ - Optimal: Not applicable for optimization but ensures all nodes are visited in level order.
157
+ - Time Complexity: O(N) where N is the number of nodes in the tree, since each node is enqueued and dequeued exactly once.
158
+ - Space Complexity: O(N) in the worst case, where the last level of the tree might have up to N/2 nodes.
159
+
160
+ Applications
161
+
162
+ - Shortest Path in Unweighted Graphs: BFS can be used to find the shortest path in an unweighted graph.
163
+ - Level-Order Display: Useful for printing the tree level by level.
164
+ - Serialization/Deserialization of Trees: Often used in algorithms that serialize and deserialize trees.
165
+ - Breadth of Trees: Can be used to calculate the breadth (width) of the tree at different levels.
166
+
167
+ In summary, level-order traversal (BFS) is an important method for tree traversal that processes nodes level by level,
168
+ ensuring that all nodes at a given level are visited before moving on to the next level.
169
+
170
+ Tree: Breadth-First Search Example LeetCode Question: 109. Convert Sorted List to Binary Search Tree
171
+ =====================================================================================================
172
+
173
+ To convert a sorted singly linked list into a height-balanced binary search tree (BST), you can use a divide-and-conquer
174
+ approach. This method ensures that the tree is balanced by recursively finding the middle element of the linked list to use
175
+ as the root of the tree (or subtree). Here's how you can implement this in Java, along with the time and space complexity analysis
176
+ (ChatGPT coded the solution 🤖).
177
+
178
+ 1. Java Implementation
179
+
180
+ * ListNode and TreeNode Definitions:
181
+ ------------------------------------
182
+
183
+ First, define the `ListNode` and `TreeNode` classes:
184
+
185
+ class ListNode {
186
+ int val;
187
+ ListNode next;
188
+ ListNode(int x) {
189
+ val = x;
190
+ next = null;
191
+ }
192
+ }
193
+
194
+ class TreeNode {
195
+ int val;
196
+ TreeNode left;
197
+ TreeNode right;
198
+ TreeNode(int x) {
199
+ val = x;
200
+ left = null;
201
+ right = null;
202
+ }
203
+ }
204
+
205
+ * Conversion Function:
206
+ ----------------------
207
+
208
+ Now, write the function to convert the sorted linked list to a height-balanced BST:
209
+
210
+ public class Solution {
211
+ private ListNode current;
212
+
213
+ public TreeNode sortedListToBST(ListNode head) {
214
+ if (head == null) return null;
215
+
216
+ // Get the size of the linked list
217
+ int size = getSize(head);
218
+ current = head;
219
+
220
+ // Build the BST
221
+ return sortedListToBSTHelper(size);
222
+ }
223
+
224
+ private int getSize(ListNode head) {
225
+ int size = 0;
226
+ while (head != null) {
227
+ head = head.next;
228
+ size++;
229
+ }
230
+ return size;
231
+ }
232
+
233
+ private TreeNode sortedListToBSTHelper(int size) {
234
+ if (size <= 0) return null;
235
+
236
+ // Recursively form the left half
237
+ TreeNode left = sortedListToBSTHelper(size / 2);
238
+
239
+ // The root node will be the current node
240
+ TreeNode root = new TreeNode(current.val);
241
+ root.left = left;
242
+
243
+ // Move to the next element
244
+ current = current.next;
245
+
246
+ // Recursively form the right half and link it to the root
247
+ root.right = sortedListToBSTHelper(size - 1 - size / 2);
248
+
249
+ return root;
250
+ }
251
+ }
252
+
253
+ * Explanation
254
+
255
+ 1. Get the Size:
256
+ - First, calculate the size of the linked list.
257
+ 2. Recursive Conversion:
258
+ - Use a recursive helper function `sortedListToBSTHelper` to convert the list to a BST.
259
+ - This function constructs the left subtree, then uses the current node as the root, and finally constructs
260
+ the right subtree.
261
+
262
+ * Time and Space Complexity
263
+
264
+ - Time Complexity: O(N)
265
+ - Each node in the list is processed exactly once, and each tree node is created exactly once. Thus, the overall
266
+ time complexity is O(N), where N is the number of nodes in the linked list.
267
+
268
+ - Space Complexity: O(log N)
269
+ - The space complexity is primarily due to the recursion stack used in the `sortedListToBSTHelper` function.
270
+ Since the function is building a balanced BST, the height of the tree (and hence the depth of the recursion)
271
+ will be O(log N). Therefore, the space complexity is O(log N).
272
+
273
+ This solution ensures that the resulting binary search tree is height-balanced and that the conversion is performed
274
+ efficiently.
0 commit comments