Skip to content

Commit

Permalink
submission of Assignment 1: Question 1
Browse files Browse the repository at this point in the history
  • Loading branch information
carryonm committed Nov 15, 2024
1 parent c5805bf commit ab859eb
Showing 1 changed file with 174 additions and 27 deletions.
201 changes: 174 additions & 27 deletions 02_activities/assignments/assignment_1.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,19 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 1,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1\n"
]
}
],
"source": [
"print((hash('your first name') % 3) + 1)"
"print((hash('Mung O') % 3) + 1)"
]
},
{
Expand Down Expand Up @@ -72,9 +80,18 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 2,
"metadata": {},
"outputs": [],
"outputs": [
{
"ename": "IndentationError",
"evalue": "expected an indented block (2850872121.py, line 8)",
"output_type": "error",
"traceback": [
"\u001b[0;36m Cell \u001b[0;32mIn[2], 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"
]
}
],
"source": [
"# Definition for a binary tree node.\n",
"# class TreeNode(object):\n",
Expand Down Expand Up @@ -193,12 +210,15 @@
]
},
{
"cell_type": "code",
"execution_count": null,
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"# Your answer here"
"# Your answer here\n",
"Paraphrase the problem: \n",
"Traverse a binary tree using the BFS method, enqueuing the elements in level order (because BFS processes nodes from the root to the deepest nodes, level by level). For each element, check(=see) if its value has already been checked/seen (i.e., if a duplicate value exists). \n",
"If a match is found, return the matched value and stop. \n",
"If no match is found, add the current element into a seen list and remove the first element from the queue and proceed to check the next element. Continue this process until all nodes have been checked. \n",
"If all nodes values are checked and no values of any 2 elements match, return \"-1\"."
]
},
{
Expand All @@ -210,11 +230,28 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# Your answer here"
"#Your answer here\n",
"#New example 1: input: root = [1, 3, 5, 3, 5, 6, 7] (BFS traversal method); ouput: 3;\n",
"root1 = Node(1)\n",
"root1.left = Node(3) #duplicate\n",
"root1.right = Node(5)\n",
"root1.left.left = Node(3) #duplicate\n",
"root1.left.right = Node(5)\n",
"root1.right.left = Node(6)\n",
"root1.right.right = Node(7)\n",
"#New example 2: input: root = [2, 3, 2, 4, 5, 6, 7] (BFS traversal method); ouput: 2;\n",
"root2 = Node(2) #duplicate\n",
"root2.left = Node(3)\n",
"root2.right = Node(2) #duplicate\n",
"root2.left.left = Node(4)\n",
"root2.left.right = Node(5)\n",
"root2.right.left = Node(6)\n",
"root2.right.right = Node(7)\n",
"\n"
]
},
{
Expand All @@ -227,11 +264,86 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 5,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3\n",
"2\n"
]
}
],
"source": [
"# Your answer here"
"# Your answer here\n",
"from collections import deque\n",
"\n",
"class Node:\n",
" def __init__(self, val=0, left=None, right=None):\n",
" self.val = val\n",
" self.left = left\n",
" self.right = right\n",
"\n",
"def bfs_recursive(queue, seen):\n",
" if not queue:\n",
" return -1 # if the queue(updated queue) is empty, no duplicates is found\n",
" \n",
" # Process the first node in the queue\n",
" current_vertex = queue[0]\n",
" \n",
" # Check if the current vertex's value has been seen before\n",
" if current_vertex.val in seen:\n",
" return current_vertex.val # Return the duplicate value\n",
" \n",
" # Add the current vertex's value to the seen set\n",
" seen.add(current_vertex.val)\n",
" \n",
" #if there are next levels/child nodes from the current_vertex, get the nodes from the next level of the tree\n",
" next_level = []\n",
" if current_vertex.left:\n",
" next_level.append(current_vertex.left)\n",
" if current_vertex.right:\n",
" next_level.append(current_vertex.right)\n",
" \n",
" #update the queue by removing the first element and add the next level child nodes of the previously first elements\n",
" return bfs_recursive(queue[1:] + next_level, seen) \n",
"\n",
"def find_duplicate(root):\n",
" #check if the tree is empty or has only 1 node, then there's no chance of duplication\n",
" if not root or (not root.left and not root.right):\n",
" return \"tree size invalid for the problem\"\n",
" \n",
" #start with a queue with the root as the 1st element (= node top level) and an empty set for tracking seen values\n",
" initial_queue = [root]\n",
" seen = set()\n",
" return bfs_recursive(initial_queue, seen)\n",
"\n",
"\n",
"#Example 1 and 2: as constructed in previous questions\n",
"#New example 1: input: root = [1, 3, 5, 3, 5, 6, 7] (BFS traversal method); ouput: 3;\n",
"root1 = Node(1)\n",
"root1.left = Node(3) #duplicate\n",
"root1.right = Node(5)\n",
"root1.left.left = Node(3) #duplicate\n",
"root1.left.right = Node(5)\n",
"root1.right.left = Node(6)\n",
"root1.right.right = Node(7)\n",
"\n",
"#New example 2: input: root = [2, 3, 2, 4, 5, 6, 7] (BFS traversal method); ouput: 2;\n",
"root2 = Node(2) #duplicate\n",
"root2.left = Node(3)\n",
"root2.right = Node(2) #duplicate\n",
"root2.left.left = Node(4)\n",
"root2.left.right = Node(5)\n",
"root2.right.left = Node(6)\n",
"root2.right.right = Node(7)\n",
"\n",
"# Testing the function\n",
"print(find_duplicate(root1)) \n",
"print(find_duplicate(root2)) \n",
"\n"
]
},
{
Expand All @@ -243,12 +355,23 @@
]
},
{
"cell_type": "code",
"execution_count": null,
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"# Your answer here"
"# Your answer here\n",
"Explanation part 1: the find_duplicate(root) part:\n",
" - check if the tree is empty or has only 1 node, then there's no chance of duplication\n",
" - start with the root as the 1st element (= node in the top level) and have an empty set to strack seen values\n",
" - the above give the initial input for the function \"find_duplicate(root)\"\n",
" \n",
"Explanation part 2: the bfs_recursive(queue, seen) part:\n",
" - 1 this is a recursive function\n",
" - 2 basically it checks the first element (\"current_vertex = queue[0]\" ) in an updated queue (the input \"queue\") has any value match in a tracking set of checked elements (the input \"seen\")\n",
" - 3 if there is a match, the value is returned; if no match, it will add the child nodes of that element to the queue and then remove the now cheked element from the queue; \n",
" - 4 Now, the queue is updated and the seen set is updated. Another round of matching process can repeat. \n",
" - 5 If no match is found after it go through all the elements in the tree, then \"-1\" is found.\n",
" - 6 point 3 above means that the nodes in the tree in checked level by level from the top to the bottom and added to the queue. So it will stop when a match in an upper level is found - which satisfy the question requirement that \"return the one with the closest distance to the root.\"\n",
" "
]
},
{
Expand All @@ -260,12 +383,35 @@
]
},
{
"cell_type": "code",
"execution_count": null,
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"# Your answer here"
"# Your answer here\n",
"\n",
"Time complexity:\n",
" - base case of find_duplicate: check if the tree has 0 or 1 nodes - O(1) \n",
" - base case of bfs_recursive: check if the queue is empty - O(1) \n",
" - bfs_recursive - the BFS method checks each node once in the tree and put elements in to the queue - O(N), this is the base for the recursive call\n",
" - bfs_recursive - at each node,\n",
" - (1) check the current_vertex has a value match in a set - O(1) \n",
" - (2) if no match, to add it to the seen set - O(1);\n",
" - (3) if no match, if there are next level nodes to the current_vertex, add it to the queue - O(1) \n",
" - (4) if no match, remove the first element from the queue - O(N)\n",
" \n",
" - TOTAL time complexity:\n",
" = O(1) + (O(1) + O(N)) * (O(1) + O(1) + O(1) + O(N))\n",
" = O(1) + O(N) * O(N)\n",
" = O(1) + O(N^2)\n",
" = O(N^2)\n",
"\n",
"Space complexity:\n",
" - the queue: the maximum number of nodes that the queue can hold at any one time - 2 levels of the tree ~ O(N) \n",
" - seen set: the masimum number of nodes ~ O(N)\n",
" - recursive call: each recursive call processes one node at a time\n",
"\n",
" - TOTAL space complexity\n",
" = O(N) + O(N) + O(N)\n",
" = O(N) \n"
]
},
{
Expand All @@ -277,12 +423,13 @@
]
},
{
"cell_type": "code",
"execution_count": null,
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"# Your answer here"
"# Your answer here\n",
"- use a hash map to track both the values and depth of the nodes\n",
"- use DFS traversal method to find out all the nodes where there are duplicated values and store them (= nodes with duplicateed value).\n",
"- in all the nodes with duplicateed value, find the one with minimum depth and return the value of that node "
]
},
{
Expand Down Expand Up @@ -344,7 +491,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.7"
"version": "3.9.19"
}
},
"nbformat": 4,
Expand Down

0 comments on commit ab859eb

Please sign in to comment.