|
21 | 21 | },
|
22 | 22 | {
|
23 | 23 | "cell_type": "code",
|
24 |
| - "execution_count": null, |
| 24 | + "execution_count": 9, |
25 | 25 | "metadata": {},
|
26 |
| - "outputs": [], |
| 26 | + "outputs": [ |
| 27 | + { |
| 28 | + "name": "stdout", |
| 29 | + "output_type": "stream", |
| 30 | + "text": [ |
| 31 | + "2\n" |
| 32 | + ] |
| 33 | + } |
| 34 | + ], |
27 | 35 | "source": [
|
28 | 36 | "import hashlib\n",
|
29 | 37 | "\n",
|
30 | 38 | "def hash_to_range(input_string: str) -> int:\n",
|
31 | 39 | " hash_object = hashlib.sha256(input_string.encode())\n",
|
32 | 40 | " hash_int = int(hash_object.hexdigest(), 16)\n",
|
33 | 41 | " return (hash_int % 3) + 1\n",
|
34 |
| - "input_string = \"your_first_name_here\"\n", |
| 42 | + "input_string = \"fan\"\n", |
35 | 43 | "result = hash_to_range(input_string)\n",
|
36 | 44 | "print(result)\n"
|
37 | 45 | ]
|
|
80 | 88 | },
|
81 | 89 | {
|
82 | 90 | "cell_type": "code",
|
83 |
| - "execution_count": null, |
| 91 | + "execution_count": 10, |
84 | 92 | "metadata": {},
|
85 |
| - "outputs": [], |
| 93 | + "outputs": [ |
| 94 | + { |
| 95 | + "ename": "IndentationError", |
| 96 | + "evalue": "expected an indented block (2850872121.py, line 8)", |
| 97 | + "output_type": "error", |
| 98 | + "traceback": [ |
| 99 | + "\u001b[0;36m Cell \u001b[0;32mIn[10], line 8\u001b[0;36m\u001b[0m\n\u001b[0;31m # TODO\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mIndentationError\u001b[0m\u001b[0;31m:\u001b[0m expected an indented block\n" |
| 100 | + ] |
| 101 | + } |
| 102 | + ], |
86 | 103 | "source": [
|
87 | 104 | "# Definition for a binary tree node.\n",
|
88 | 105 | "# class TreeNode(object):\n",
|
|
130 | 147 | },
|
131 | 148 | {
|
132 | 149 | "cell_type": "code",
|
133 |
| - "execution_count": null, |
| 150 | + "execution_count": 27, |
134 | 151 | "metadata": {},
|
135 | 152 | "outputs": [],
|
136 | 153 | "source": [
|
137 | 154 | "# Definition for a binary tree node.\n",
|
138 |
| - "# class TreeNode(object):\n", |
139 |
| - "# def __init__(self, val = 0, left = None, right = None):\n", |
140 |
| - "# self.val = val\n", |
141 |
| - "# self.left = left\n", |
142 |
| - "# self.right = right\n", |
| 155 | + "from typing import List\n", |
| 156 | + "\n", |
| 157 | + "class TreeNode(object):\n", |
| 158 | + " def __init__(self, val = 0, left = None, right = None):\n", |
| 159 | + " self.val = val\n", |
| 160 | + " self.left = left\n", |
| 161 | + " self.right = right\n", |
143 | 162 | "def bt_path(root: TreeNode) -> List[List[int]]:\n",
|
144 |
| - " # TODO" |
| 163 | + " def dfs(node, path):\n", |
| 164 | + " if node:\n", |
| 165 | + " path.append(node.val)\n", |
| 166 | + " if not node.left and not node.right:\n", |
| 167 | + " res.append(path[:])\n", |
| 168 | + " else:\n", |
| 169 | + " dfs(node.left, path)\n", |
| 170 | + " dfs(node.right, path)\n", |
| 171 | + " path.pop()\n", |
| 172 | + " res = []\n", |
| 173 | + " dfs(root, [])\n", |
| 174 | + " return res" |
145 | 175 | ]
|
146 | 176 | },
|
147 | 177 | {
|
|
201 | 231 | ]
|
202 | 232 | },
|
203 | 233 | {
|
204 |
| - "cell_type": "code", |
205 |
| - "execution_count": null, |
| 234 | + "cell_type": "markdown", |
206 | 235 | "metadata": {},
|
207 |
| - "outputs": [], |
208 | 236 | "source": [
|
209 |
| - "# Your answer here" |
| 237 | + "Problem: Given a binary tree, I need to find all possible paths from the root node to the leaf nodes, each path should be represented as a list of node values, this is a DFS." |
210 | 238 | ]
|
211 | 239 | },
|
212 | 240 | {
|
|
218 | 246 | },
|
219 | 247 | {
|
220 | 248 | "cell_type": "code",
|
221 |
| - "execution_count": null, |
| 249 | + "execution_count": 20, |
222 | 250 | "metadata": {},
|
223 | 251 | "outputs": [],
|
224 | 252 | "source": [
|
225 |
| - "# Your answer here" |
| 253 | + "def test_bt_path(root: TreeNode, expected: List[str]):\n", |
| 254 | + " result = bt_path(root)\n", |
| 255 | + " if sorted(result) == sorted(expected):\n", |
| 256 | + " print(f\"Test passed! Expected {expected}\")\n", |
| 257 | + " else:\n", |
| 258 | + " print(f\"Test failed! Expected {expected}, but got {result}\")" |
| 259 | + ] |
| 260 | + }, |
| 261 | + { |
| 262 | + "cell_type": "code", |
| 263 | + "execution_count": 28, |
| 264 | + "metadata": {}, |
| 265 | + "outputs": [ |
| 266 | + { |
| 267 | + "name": "stdout", |
| 268 | + "output_type": "stream", |
| 269 | + "text": [ |
| 270 | + "Test passed! Expected [[5, 4], [5, 6, 7]]\n", |
| 271 | + "Test passed! Expected [[10, 5, 3], [10, 5, 8], [10, 15, 12]]\n" |
| 272 | + ] |
| 273 | + } |
| 274 | + ], |
| 275 | + "source": [ |
| 276 | + "root_example_3 = TreeNode(5)\n", |
| 277 | + "root_example_3.left = TreeNode(4)\n", |
| 278 | + "root_example_3.right = TreeNode(6)\n", |
| 279 | + "root_example_3.right.left = TreeNode(7)\n", |
| 280 | + " \n", |
| 281 | + "expected_example_3 = [[5,4], [5,6,7]]\n", |
| 282 | + "test_bt_path(root_example_3, expected_example_3)\n", |
| 283 | + " \n", |
| 284 | + "\n", |
| 285 | + "root_example_4 = TreeNode(10)\n", |
| 286 | + "root_example_4.left = TreeNode(5)\n", |
| 287 | + "root_example_4.right = TreeNode(15)\n", |
| 288 | + "root_example_4.left.left = TreeNode(3)\n", |
| 289 | + "root_example_4.left.right = TreeNode(8)\n", |
| 290 | + "root_example_4.right.left = TreeNode(12)\n", |
| 291 | + " \n", |
| 292 | + "expected_example_4 = [[10, 5, 3], [10, 5, 8], [10, 15, 12]]\n", |
| 293 | + " \n", |
| 294 | + "test_bt_path(root_example_4, expected_example_4)" |
226 | 295 | ]
|
227 | 296 | },
|
228 | 297 | {
|
|
239 | 308 | "metadata": {},
|
240 | 309 | "outputs": [],
|
241 | 310 | "source": [
|
242 |
| - "# Your answer here" |
| 311 | + "def bt_path(root: TreeNode) -> List[List[int]]:\n", |
| 312 | + " def dfs(node, path):\n", |
| 313 | + " if node:\n", |
| 314 | + " path.append(node.val)\n", |
| 315 | + " if not node.left and not node.right:\n", |
| 316 | + " res.append(path[:])\n", |
| 317 | + " else:\n", |
| 318 | + " dfs(node.left, path)\n", |
| 319 | + " dfs(node.right, path)\n", |
| 320 | + " path.pop()\n", |
| 321 | + " res = []\n", |
| 322 | + " dfs(root, [])\n", |
| 323 | + " return res" |
243 | 324 | ]
|
244 | 325 | },
|
245 | 326 | {
|
|
251 | 332 | ]
|
252 | 333 | },
|
253 | 334 | {
|
254 |
| - "cell_type": "code", |
255 |
| - "execution_count": null, |
| 335 | + "cell_type": "markdown", |
256 | 336 | "metadata": {},
|
257 |
| - "outputs": [], |
258 | 337 | "source": [
|
259 |
| - "# Your answer here" |
| 338 | + "-----------\n", |
| 339 | + "The solution uses a recursive DFS to explore all paths from the root to the leaves. Here’s how it works:\n", |
| 340 | + "- **DFS Helper Function**: dfs(node, path, res) takes:\n", |
| 341 | + " - node: Current node being processed.\n", |
| 342 | + " - path: A list storing the current path’s node values as strings.\n", |
| 343 | + " - res: The result list collecting all complete paths.\n", |
| 344 | + "- **Base Case**: If node is None (empty subtree), return without doing anything.\n", |
| 345 | + "- **Path Building**: Add the current node’s value to path. This tracks the sequence from root to the current node.\n", |
| 346 | + "- **Leaf Check**: If the node has no left or right child (not node.left and not node.right), it’s a leaf. push to res []\n", |
| 347 | + "- **Recursion**: Recursively call dfs on the left and right children to explore all possible paths.\n", |
| 348 | + "- **Backtrack**: path.pop() backtracks by removing the last element from the path list, allowing the algorithm to go back to previous state and explore other paths.\n", |
| 349 | + "-----------" |
260 | 350 | ]
|
261 | 351 | },
|
262 | 352 | {
|
|
268 | 358 | ]
|
269 | 359 | },
|
270 | 360 | {
|
271 |
| - "cell_type": "code", |
272 |
| - "execution_count": null, |
| 361 | + "cell_type": "markdown", |
273 | 362 | "metadata": {},
|
274 |
| - "outputs": [], |
275 | 363 | "source": [
|
276 |
| - "# Your answer here" |
| 364 | + "-----------\n", |
| 365 | + "Time Complexity: O(N*logN). \n", |
| 366 | + "- DFS Traversal: This solution visits each node exactly once, so the time complexity is (O(N)), where (N) is the number of nodes in the binary tree. \n", |
| 367 | + "- Path Construct: For each path, we append and pop values from the path list, where LogN is the length of the path, and height of the tree (H).\n", |
| 368 | + "- Overall time complexity remains (O(N * H))\n", |
| 369 | + "\n", |
| 370 | + "Space Complexity: O(N + H). \n", |
| 371 | + "- Recursive Stack: The space complexity due to the recursive stack is (O(H)) where (H) is the height of the tree.\n", |
| 372 | + "- Path List: We use a list path to store the current path, which can take up to the length of the longest path, i.e., (O(H)).\n", |
| 373 | + "- Result List: The result list res stores all paths, and in the worst case, it could contain all possible paths from root to leaf nodes, which is (O(N)).\n", |
| 374 | + "- Overall space complexity is (O(N + H)).\n", |
| 375 | + " \n", |
| 376 | + "-----------" |
277 | 377 | ]
|
278 | 378 | },
|
279 | 379 | {
|
280 | 380 | "cell_type": "markdown",
|
281 | 381 | "metadata": {},
|
282 | 382 | "source": [
|
283 | 383 | "\n",
|
284 |
| - "- Explain the thinking to an alternative solution (no coding required, but a classmate reading this should be able to code it up based off your text)\n" |
| 384 | + " - Explain the thinking to an alternative solution (no coding required, but a classmate reading this should be able to code it up based off your text)\n" |
285 | 385 | ]
|
286 | 386 | },
|
287 | 387 | {
|
288 |
| - "cell_type": "code", |
289 |
| - "execution_count": null, |
| 388 | + "cell_type": "markdown", |
290 | 389 | "metadata": {},
|
291 |
| - "outputs": [], |
292 | 390 | "source": [
|
293 |
| - "# Your answer here" |
| 391 | + "-----------\n", |
| 392 | + "To solve this problem iteratively using a stack:\n", |
| 393 | + "\n", |
| 394 | + "1. Initialize Stack: Start with the root node, an empty path list.\n", |
| 395 | + "2. Iterate While Stack is Not Empty:\n", |
| 396 | + " 1. Pop the current node, its path, and whether it's a leaf from the stack.\n", |
| 397 | + " 2. If the current node is a leaf, add the constructed path to the result list.\n", |
| 398 | + " 3. If the current node has a right child, push it onto the stack with the updated path and mark it as not a leaf.\n", |
| 399 | + " 4. If the current node has a left child, push it onto the stack with the updated path and mark it as not a leaf.\n", |
| 400 | + "3. Return Result List: After processing all nodes, return the result list containing all paths.\n", |
| 401 | + "\n", |
| 402 | + "This iterative approach ensures that each node is visited exactly once and constructs the paths efficiently using a stack.\n", |
| 403 | + "\n", |
| 404 | + "-----------" |
294 | 405 | ]
|
295 | 406 | },
|
296 | 407 | {
|
|
338 | 449 | ],
|
339 | 450 | "metadata": {
|
340 | 451 | "kernelspec": {
|
341 |
| - "display_name": "Python 3", |
| 452 | + "display_name": "dsi_participant", |
342 | 453 | "language": "python",
|
343 | 454 | "name": "python3"
|
344 | 455 | },
|
|
352 | 463 | "name": "python",
|
353 | 464 | "nbconvert_exporter": "python",
|
354 | 465 | "pygments_lexer": "ipython3",
|
355 |
| - "version": "3.11.7" |
| 466 | + "version": "3.9.7" |
356 | 467 | }
|
357 | 468 | },
|
358 | 469 | "nbformat": 4,
|
|
0 commit comments