From 83627a0395d82fda8653299cef5400364493f73a Mon Sep 17 00:00:00 2001 From: shaurya22c Date: Mon, 31 Aug 2026 16:34:28 -0400 Subject: [PATCH 1/2] Completed BFS-1 homework --- course_schedule.py | 65 ++++++++++++++++++++++++++++++++++++++++ level_order_traversal.py | 64 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 course_schedule.py create mode 100644 level_order_traversal.py diff --git a/course_schedule.py b/course_schedule.py new file mode 100644 index 00000000..179a4143 --- /dev/null +++ b/course_schedule.py @@ -0,0 +1,65 @@ +""" +APPROACH: +1. Build a graph where each course points to the courses that depend on it (its "children"). +2. Track the indegree (number of prerequisites) for every course. +3. Start with all courses that have zero prerequisites, since those can be taken right away. +4. Process courses one by one, and each time a course is "taken", reduce the indegree of its dependents. +5. If a dependent's indegree hits zero, it becomes takeable, so add it to the queue. + +PATTERN: +Topological Sort (Kahn's Algorithm using BFS) + +TIME COMPLEXITY: +O(V + E) - V is numCourses, E is number of prerequisite pairs, each visited once + +SPACE COMPLEXITY: +O(V + E) - graph stores all edges, plus indegree array and queue of size V + +EXAMPLE: +Input: +numCourses = 4 +prerequisites = [[1,0],[2,0],[3,1],[3,2]] + +Output: True +Why: order 0 -> 1 -> 2 -> 3 (or 0 -> 2 -> 1 -> 3) satisfies all prerequisites, no cycle exists +""" + +class Solution: + def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool: + graph = {} # maps each course to list of courses that depend on it + + for i in range(numCourses): + graph[i] = [] # initialize empty dependents list for every course + + indegree = [0] * numCourses # tracks number of prerequisites per course + + for course, prereq in prerequisites: + graph[prereq].append(course) # prereq must be taken before course + + for course, prereq in prerequisites: + indegree[course] = indegree[course] + 1 # count each prerequisite requirement + + queue = collections.deque() # queue used for BFS (Kahn's algorithm) + + # start with all courses that have no prerequisites + for i in range(numCourses): + if indegree[i] == 0: + queue.append(i) + + while queue: + current_course = queue.popleft() # take this course now + + # unlock dependent courses by reducing their prerequisite count + for neighbor in graph[current_course]: + indegree[neighbor] = indegree[neighbor] - 1 + + # if a course has no more prerequisites left, it can now be taken + if indegree[neighbor] == 0: + queue.append(neighbor) + + # if any course still has prerequisites left, there was a cycle + for i in range(numCourses): + if indegree[i] != 0: + return False + + return True # all courses could be taken, no cycle found \ No newline at end of file diff --git a/level_order_traversal.py b/level_order_traversal.py new file mode 100644 index 00000000..a4a60e4b --- /dev/null +++ b/level_order_traversal.py @@ -0,0 +1,64 @@ +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right + +""" +APPROACH: +1. If the tree is empty, return an empty list right away. +2. Use a queue to do BFS, starting with just the root node. +3. Process the tree one level at a time by tracking how many nodes are in the queue at the start of each level. +4. For each node processed, record its value and add its children (if any) to the queue for the next level. +5. Once a level is fully processed, save it as one list inside the final result. + +PATTERN: +Tree BFS / Level Order Traversal + +TIME COMPLEXITY: +O(n) - every node is visited and processed exactly once + +SPACE COMPLEXITY: +O(n) - queue can hold up to one full level of nodes, and result stores all node values + +EXAMPLE: +Input: + 3 + / \ + 9 20 + / \ + 15 7 + +Output: [[3], [9, 20], [15, 7]] +Why: level 0 has just 3, level 1 has 9 and 20, level 2 has 15 and 7 +""" + +class Solution: + def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: + + if not root: + return [] # empty tree has no levels to return + + result = [] # stores final list of levels + queue = collections.deque() # queue used for BFS + + queue.append(root) # start BFS with the root node + + while queue: + + level_size = len(queue) # number of nodes in current level + current_level = [] # values for this level + + for i in range(level_size): + current_node = queue.popleft() # process next node in this level + current_level.append(current_node.val) # record its value + + # add children to queue so they get processed in the next level + if current_node.left: + queue.append(current_node.left) + if current_node.right: + queue.append(current_node.right) + + result.append(current_level) # save this fully processed level + return result # all levels collected \ No newline at end of file From 6ee739cda7dbfb7d5e9ca469b27fc9920e9623e1 Mon Sep 17 00:00:00 2001 From: shaurya22c Date: Mon, 31 Aug 2026 16:40:46 -0400 Subject: [PATCH 2/2] right side view of binary tree --- right_side_view.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 right_side_view.py diff --git a/right_side_view.py b/right_side_view.py new file mode 100644 index 00000000..9a92223a --- /dev/null +++ b/right_side_view.py @@ -0,0 +1,33 @@ +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def rightSideView(self, root: Optional[TreeNode]) -> List[int]: + + if root is None: + return [] + + result = [] + q = collections.deque() + q.append(root) + + while q: + level_size = len(q) + + for i in range(level_size): + + current_node = q.popleft() + + if i == level_size - 1: + result.append(current_node.val) + + if current_node.left: + q.append(current_node.left) + + if current_node.right: + q.append(current_node.right) + + return result \ No newline at end of file