Skip to content

Commit d90ccfc

Browse files
committed
Algorithms & Data Structures Module: Assignment 1
1 parent f7e9d9b commit d90ccfc

File tree

1 file changed

+188
-34
lines changed

1 file changed

+188
-34
lines changed

02_activities/assignments/assignment_1.ipynb

Lines changed: 188 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,25 @@
2121
},
2222
{
2323
"cell_type": "code",
24-
"execution_count": null,
24+
"execution_count": 4,
2525
"metadata": {},
26-
"outputs": [],
26+
"outputs": [
27+
{
28+
"name": "stdout",
29+
"output_type": "stream",
30+
"text": [
31+
"1\n"
32+
]
33+
}
34+
],
2735
"source": [
2836
"import hashlib\n",
2937
"\n",
3038
"def hash_to_range(input_string: str) -> int:\n",
3139
" hash_object = hashlib.sha256(input_string.encode())\n",
3240
" hash_int = int(hash_object.hexdigest(), 16)\n",
3341
" return (hash_int % 3) + 1\n",
34-
"input_string = \"your_first_name_here\"\n",
42+
"input_string = \"whitney\"\n",
3543
"result = hash_to_range(input_string)\n",
3644
"print(result)\n"
3745
]
@@ -80,18 +88,100 @@
8088
},
8189
{
8290
"cell_type": "code",
83-
"execution_count": null,
91+
"execution_count": 50,
8492
"metadata": {},
8593
"outputs": [],
8694
"source": [
8795
"# Definition for a binary tree node.\n",
88-
"# class TreeNode(object):\n",
89-
"# def __init__(self, val = 0, left = None, right = None):\n",
90-
"# self.val = val\n",
91-
"# self.left = left\n",
92-
"# self.right = right\n",
96+
"class TreeNode(object):\n",
97+
" def __init__(self, val = 0, left = None, right = None):\n",
98+
" self.val = val\n",
99+
" self.left = left\n",
100+
" self.right = right\n",
101+
"\n",
102+
"# Method to convert list into tree object\n",
103+
"def list_to_tree(treeList: list[int]) -> TreeNode:\n",
104+
" \n",
105+
" # Track tree length \n",
106+
" index = len(treeList)\n",
107+
"\n",
108+
" def build_tree(i: int=0) -> TreeNode:\n",
109+
" # Empty list\n",
110+
" if (index == 0):\n",
111+
" return None\n",
112+
" \n",
113+
" # Don't go further than last item of the tree\n",
114+
" if (i >= index):\n",
115+
" return None\n",
116+
" \n",
117+
" # Set up the tree recursively\n",
118+
" node = TreeNode(treeList[i])\n",
119+
" node.left = build_tree(2*i +1)\n",
120+
" node.right = build_tree(2*i +2)\n",
121+
" \n",
122+
" return node\n",
123+
" \n",
124+
" return build_tree()\n",
125+
"\n",
126+
"\n",
127+
"# Given a tree, print the first duplicate value\n",
93128
"def is_duplicate(root: TreeNode) -> int:\n",
94-
" # TODO"
129+
" # Return -1 if empty\n",
130+
" if (root == None):\n",
131+
" return -1\n",
132+
" \n",
133+
" # Create a list to store visited values\n",
134+
" visited = []\n",
135+
"\n",
136+
" # Create a queue with the tree\n",
137+
" queue = [root]\n",
138+
"\n",
139+
" while queue:\n",
140+
" # Pop the next tree node\n",
141+
" node = queue.pop(0)\n",
142+
" \n",
143+
" # Return the duplicate value once found\n",
144+
" if (node.val in visited):\n",
145+
" return node.val\n",
146+
"\n",
147+
" # If no duplicates, add the value into our visited list\n",
148+
" visited.append(node.val)\n",
149+
"\n",
150+
" # Insert leaf nodes into queue to check next layer\n",
151+
" if (node.left != None):\n",
152+
" queue.append(node.left)\n",
153+
" if (node.right != None):\n",
154+
" queue.append(node.right)\n",
155+
"\n",
156+
" # Return -1 if no duplicates found above\n",
157+
" return -1\n"
158+
]
159+
},
160+
{
161+
"cell_type": "code",
162+
"execution_count": 54,
163+
"metadata": {},
164+
"outputs": [
165+
{
166+
"name": "stdout",
167+
"output_type": "stream",
168+
"text": [
169+
"2\n",
170+
"10\n",
171+
"-1\n"
172+
]
173+
}
174+
],
175+
"source": [
176+
"# Test examples on the code above\n",
177+
"root = list_to_tree([1,2,2,3,5,6,7])\n",
178+
"print(is_duplicate(root))\n",
179+
"\n",
180+
"root = list_to_tree([1,10,2,3,10,12,12])\n",
181+
"print(is_duplicate(root))\n",
182+
"\n",
183+
"root = list_to_tree([10,9,8,7])\n",
184+
"print(is_duplicate(root))\n"
95185
]
96186
},
97187
{
@@ -201,12 +291,10 @@
201291
]
202292
},
203293
{
204-
"cell_type": "code",
205-
"execution_count": null,
294+
"cell_type": "markdown",
206295
"metadata": {},
207-
"outputs": [],
208296
"source": [
209-
"# Your answer here"
297+
"The problem is asking for the first duplicate value that appears in the binary tree, closest to the root (first) node. If there are no duplicates, then a default of -1 is returned as the value."
210298
]
211299
},
212300
{
@@ -217,12 +305,16 @@
217305
]
218306
},
219307
{
220-
"cell_type": "code",
221-
"execution_count": null,
308+
"cell_type": "markdown",
222309
"metadata": {},
223-
"outputs": [],
224310
"source": [
225-
"# Your answer here"
311+
"*Example 1*\n",
312+
"Input: root = [1,7,7,2,2,5,5]\n",
313+
"Output: 7\n",
314+
"\n",
315+
"*Example 2*\n",
316+
"Input: root = [10,9,8,7,1,2,3,4,5,6]\n",
317+
"Output: -1"
226318
]
227319
},
228320
{
@@ -235,11 +327,73 @@
235327
},
236328
{
237329
"cell_type": "code",
238-
"execution_count": null,
330+
"execution_count": 49,
239331
"metadata": {},
240332
"outputs": [],
241333
"source": [
242-
"# Your answer here"
334+
"# Definition for a binary tree node.\n",
335+
"class TreeNode(object):\n",
336+
" def __init__(self, val = 0, left = None, right = None):\n",
337+
" self.val = val\n",
338+
" self.left = left\n",
339+
" self.right = right\n",
340+
"\n",
341+
"# Method to convert list into tree object\n",
342+
"def list_to_tree(treeList: list[int]) -> TreeNode:\n",
343+
" \n",
344+
" # Track tree length \n",
345+
" index = len(treeList)\n",
346+
"\n",
347+
" def build_tree(i: int=0) -> TreeNode:\n",
348+
" # Empty list\n",
349+
" if (index == 0):\n",
350+
" return None\n",
351+
" \n",
352+
" # Don't go further than last item of the tree\n",
353+
" if (i >= index):\n",
354+
" return None\n",
355+
" \n",
356+
" # Set up the tree recursively\n",
357+
" node = TreeNode(treeList[i])\n",
358+
" node.left = build_tree(2*i +1)\n",
359+
" node.right = build_tree(2*i +2)\n",
360+
" \n",
361+
" return node\n",
362+
" \n",
363+
" return build_tree()\n",
364+
"\n",
365+
"\n",
366+
"# Given a tree, print the first duplicate value\n",
367+
"def is_duplicate(root: TreeNode) -> int:\n",
368+
" # Return -1 if empty\n",
369+
" if (root == None):\n",
370+
" return -1\n",
371+
" \n",
372+
" # Create a list to store visited values\n",
373+
" visited = []\n",
374+
"\n",
375+
" # Create a queue with the tree\n",
376+
" queue = [root]\n",
377+
"\n",
378+
" while queue:\n",
379+
" # Pop the next tree node\n",
380+
" node = queue.pop(0)\n",
381+
" \n",
382+
" # Return the duplicate value once found\n",
383+
" if (node.val in visited):\n",
384+
" return node.val\n",
385+
"\n",
386+
" # If no duplicates, add the value into our visited list\n",
387+
" visited.append(node.val)\n",
388+
"\n",
389+
" # Insert leaf nodes into queue to check next layer\n",
390+
" if (node.left != None):\n",
391+
" queue.append(node.left)\n",
392+
" if (node.right != None):\n",
393+
" queue.append(node.right)\n",
394+
"\n",
395+
" # Return -1 if no duplicates found above\n",
396+
" return -1\n"
243397
]
244398
},
245399
{
@@ -251,12 +405,10 @@
251405
]
252406
},
253407
{
254-
"cell_type": "code",
255-
"execution_count": null,
408+
"cell_type": "markdown",
256409
"metadata": {},
257-
"outputs": [],
258410
"source": [
259-
"# Your answer here"
411+
"My solution first takes the provided list and turns it into a Tree structure. Afterwards, I use breadth-first search implemented with a queue to inspect the tree in order to find the nearest node that is a duplicated value. The visited values are stored in a list as the tree nodes are pushed into the queue, so once the first duplicated value is popped from the queue, it can be found in the visited list and returned immediately. Once all nodes are visited with no duplicates found, it will default to returning -1."
260412
]
261413
},
262414
{
@@ -268,12 +420,16 @@
268420
]
269421
},
270422
{
271-
"cell_type": "code",
272-
"execution_count": null,
423+
"cell_type": "markdown",
273424
"metadata": {},
274-
"outputs": [],
275425
"source": [
276-
"# Your answer here"
426+
"*Time Complexity*\n",
427+
"O(n+e)\n",
428+
"This implements BFS using a single while loop with a queue that would go through each n node and edge e of the tree once in the worst case, so the run time complexity is O(n+e). \n",
429+
"\n",
430+
"*Space Complexity*\n",
431+
"O(n)\n",
432+
"In the worst case scenario, we would inspect and store every value of the tree in a visited list, so the space complexity is O(n)."
277433
]
278434
},
279435
{
@@ -285,12 +441,10 @@
285441
]
286442
},
287443
{
288-
"cell_type": "code",
289-
"execution_count": null,
444+
"cell_type": "markdown",
290445
"metadata": {},
291-
"outputs": [],
292446
"source": [
293-
"# Your answer here"
447+
"An alternative solution can be to traverse the whole tree first and then use a hash table / dictionary to store each of the node's value and the distance from the root. Then use a for loop to iterate over the hash table to find duplicate values. Then compare the distances for the duplicate values to see which one has the smallest distance from the root and return that value. If no duplicates found, then return -1 as default."
294448
]
295449
},
296450
{
@@ -338,7 +492,7 @@
338492
],
339493
"metadata": {
340494
"kernelspec": {
341-
"display_name": "Python 3",
495+
"display_name": "dsi_participant",
342496
"language": "python",
343497
"name": "python3"
344498
},
@@ -352,7 +506,7 @@
352506
"name": "python",
353507
"nbconvert_exporter": "python",
354508
"pygments_lexer": "ipython3",
355-
"version": "3.11.7"
509+
"version": "3.9.20"
356510
}
357511
},
358512
"nbformat": 4,

0 commit comments

Comments
 (0)