Skip to content

Commit

Permalink
Assignment_1
Browse files Browse the repository at this point in the history
  • Loading branch information
Lisa Feeney committed Nov 15, 2024
1 parent 6b5ec9b commit 70b1786
Showing 1 changed file with 139 additions and 11 deletions.
150 changes: 139 additions & 11 deletions 02_activities/assignments/assignment_1.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@
"# self.val = val\n",
"# self.left = left\n",
"# self.right = right\n",
"def is_duplicate(root: TreeNode) -> int:\n",
" # TODO"
"# def is_duplicate(root: TreeNode) -> int:\n",
" # TODO\n"
]
},
{
Expand Down Expand Up @@ -198,7 +198,23 @@
"metadata": {},
"outputs": [],
"source": [
"# Your answer here"
"# We are looking to solve the problem of identifying the first duplicate value in a binary tree \n",
"# using breadth-first traversal (BFT) \n",
"\n",
"# BFT:\n",
"# Step 1: If the tree is empty, it immediately returns -1 (no duplicates exist)\n",
"# Step 2: The function then goes through each node in the tree level by level.\n",
"# For each node, it checks to see if the node’s value has been seen before:\n",
"# If the value exists in the seen set, it returns that value immediately, as the first duplicate.\n",
"# If the value hasn't been seen, it adds it to the seen set and continues.\n",
"# Step 3: It then enqueues the node’s left and right children, if they exist, for further traversal. \n",
"# Step 4: If no duplicates are found by traversal completion, it returns -1 \n",
"\n",
"# Even simplier explanation:\n",
"# We are given the root of a binary tree, and asked to check whether it is contains a duplicate value. \n",
"# If a duplicate exists, it returns the duplicate value. \n",
"# If there are multiple duplicates, it returns the one with the closest distance to the root. \n",
"# If no duplicate exists, it returns -1.\n"
]
},
{
Expand All @@ -212,9 +228,60 @@
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"9\n"
]
}
],
"source": [
"# Your answer here"
"# Input: root = [1, 2, 3, 4, 5, 9, 9] \n",
"# Output: 9\n",
"\n",
"# Create the tree nodes\n",
"root = TreeNode(1)\n",
"root.left = TreeNode(2)\n",
"root.right = TreeNode(3)\n",
"root.left.left = TreeNode(4)\n",
"root.left.right = TreeNode(5)\n",
"root.right.left = TreeNode(9)\n",
"root.right.right = TreeNode(9)\n",
"\n",
"# Run the function\n",
"print(is_duplicate(root))"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"9\n"
]
}
],
"source": [
"# Input: root = [1, 9, 9, 4, 5, 7, 8] \n",
"# Output: 9\n",
"\n",
"# Create the tree nodes\n",
"root = TreeNode(1)\n",
"root.left = TreeNode(9)\n",
"root.right = TreeNode(9)\n",
"root.left.left = TreeNode(4)\n",
"root.left.right = TreeNode(5)\n",
"root.right.left = TreeNode(7)\n",
"root.right.right = TreeNode(8)\n",
"\n",
"# Run the function\n",
"print(is_duplicate(root))"
]
},
{
Expand All @@ -231,7 +298,38 @@
"metadata": {},
"outputs": [],
"source": [
"# Your answer here"
"from collections import deque\n",
"\n",
"# Definition for a binary tree node.\n",
"class TreeNode:\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 is_duplicate(root: TreeNode) -> int:\n",
" if not root:\n",
" return -1\n",
"\n",
" seen = set() # To store seen values\n",
" queue = deque([root]) # Queue for level-order traversal\n",
"\n",
" while queue:\n",
" node = queue.popleft()\n",
"\n",
" # Check if the current node's value is a duplicate\n",
" if node.val in seen:\n",
" return node.val # Return the first duplicate value found\n",
"\n",
" seen.add(node.val) # Mark the current node's value as seen\n",
"\n",
" # Add children to the queue for further exploration\n",
" if node.left:\n",
" queue.append(node.left)\n",
" if node.right:\n",
" queue.append(node.right)\n",
"\n",
" return -1 # If no duplicate is found"
]
},
{
Expand All @@ -248,7 +346,16 @@
"metadata": {},
"outputs": [],
"source": [
"# Your answer here"
"# Breadth-first traversal ensures that any duplicate value \n",
"# closer to the root is found first because it explores nodes layer-by-layer.\n",
"\n",
"# The approach is fast and efficient: The seen set keeps track of all node values encountered during the traversal.\n",
"# Checking if a value is in the set is very fast and adding a value to the set is also fast\n",
"# ensuring that duplicates can be detected efficiently.\n",
"\n",
"# As soon as the function detects that a node's value is already in the seen set, it immediately returns \n",
"# that value as the first duplicate. Ensuring that the solution is optimal and stops as soon as the problem is solved, \n",
"# without traversing unnecessary parts of the tree.\n"
]
},
{
Expand All @@ -265,7 +372,19 @@
"metadata": {},
"outputs": [],
"source": [
"# Your answer here"
"# Time Complexity: 𝑂(𝑛) where 𝑛 is the number of nodes in the tree\n",
"# Breadth-First Traversal:\n",
"# - Each node in the binary tree is visited exactly once during the traversal. \n",
"# - If there are 𝑛 nodes in the tree, the traversal takes 𝑂(𝑛) time.\n",
"# Set Operations:\n",
"# - Checking whether a value is in the seen set and adding a value to the set both take average 𝑂(1) time.\n",
"# - These operations are performed once for each node.\n",
"\n",
"# Space Complexity: 𝑂(𝑛)\n",
"# Queue (for Level-Order Traversal):\n",
"# - The queue stores nodes at the current level during traversal.\n",
"# Set (for Tracking Seen Values): The seen set stores the values of all visited nodes.\n",
"# - In the worst case (when no duplicates exist), the set will contain all 𝑛 node values."
]
},
{
Expand All @@ -282,7 +401,16 @@
"metadata": {},
"outputs": [],
"source": [
"# Your answer here"
"# An alternative to the breadth-first traversal is to use a pre-order depth-first traversal \n",
"# The tree is explored by checking the current node first, then the left subtree, and finally the right subtree.\n",
"# - specifically, depth-first explores one branch fully before moving to the next.\n",
"# The seen set keeps track of node values found during traversal and if the value is already in the set, \n",
"# it is returned as the first duplicate.\n",
"# If a duplicate is found in the left or right subtree, the function stops and sends that result back right away\n",
"\n",
"# Unlike breadth-first (which ensures the first duplicate closest to the root is detected first), \n",
"# depth-first finds the first duplicate based on its traversal order (in this case pre-order), \n",
"# which might not always be the closest to the root."
]
},
{
Expand Down Expand Up @@ -330,7 +458,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"display_name": "dsi_participant",
"language": "python",
"name": "python3"
},
Expand All @@ -344,7 +472,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.7"
"version": "3.9.15"
}
},
"nbformat": 4,
Expand Down

0 comments on commit 70b1786

Please sign in to comment.