diff --git a/bt-level-order.py b/bt-level-order.py new file mode 100644 index 00000000..df7db410 --- /dev/null +++ b/bt-level-order.py @@ -0,0 +1,30 @@ +# 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 levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: + # bfs - use queue fifo, popleft() + # when queue is empty, we know level is complete + levels=[] + if not root: + return levels + + # levels = [[3],[]] + # q = [9,20] + level=0 + queue = deque([root]) + while queue: + levels.append([]) + for i in range(len(queue)): + node = queue.popleft() + levels[level].append(node.val) + if node.left: + queue.append(node.left) + if node.right: + queue.append(node.right) + level+=1 + + return levels \ No newline at end of file diff --git a/course-sched.py b/course-sched.py new file mode 100644 index 00000000..298a4273 --- /dev/null +++ b/course-sched.py @@ -0,0 +1,90 @@ +# Keep track of indegrees using topological sort + +# BFS +# O(V+E) time, O(V+E) space +class Solution: + def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool: + indegrees = [0] * numCourses + graph = {} + + for pr in prerequisites: + # build the topological sort + indegrees[pr[0]] += 1 + # build the adjacency list + if pr[1] not in graph: + graph[pr[1]] = [] + graph[pr[1]].append(pr[0]) + + count = 0 + q = deque() + + for i in range(numCourses): + # finds the roots - which have 0 prerequisites. Side note - in this problem 1 graph can have many roots + if indegrees[i] == 0: + q.append(i) + count += 1 + + # every single course has at least 1 prerequisite (deadlock cycle) + if not q: + return False + # all courses have 0 prereqs. Every course is already ready to take - no need for bfs + if count == numCourses: + return True + + while q: + curr = q.popleft() + dependencies = graph.get(curr) + if dependencies: + for dep in dependencies: + indegrees[dep] -= 1 + if indegrees[dep] == 0: + q.append(dep) + count += 1 + # to finish all courses, count must eventually equal numCourses. + # as soon as you decrement indegree to 0 for a course, you add it to the queue and increment count + # if count == numCourses, you already found a valid path for all courses + if count == numCourses: + return True + + return False + + +# DFS O(V+E) time, O(V+E) space +class Solution: + def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool: + self.map = {} + self.path = [False] * numCourses + self.visited = [False] * numCourses + + for pr in prerequisites: + if pr[1] not in self.map: + self.map[pr[1]] = [] + self.map[pr[1]].append(pr[0]) + + for i in range(numCourses): + if self.hasCycle(i): + return False + + return True + + def hasCycle(self, i: int) -> bool: + if self.visited[i]: + return False + + if self.path[i]: + return True + + self.path[i] = True + + neighbours = self.map.get(i) + if neighbours is not None: + for ne in neighbours: + if self.hasCycle(ne): + return True + + # you could have A->B->C and A->C. if you don't set path c back to false after exploring through b, the algorithm would think a-c is a cycle + self.path[i] = False + self.visited[i] = True + + return False + diff --git a/right-side-view.py b/right-side-view.py new file mode 100644 index 00000000..22e9ce1f --- /dev/null +++ b/right-side-view.py @@ -0,0 +1,45 @@ +# O(n) time, O(h) space +# DFS +# 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]: + result = [] + self.helper(root,0,result) + return result + + def helper(self, root, level, result): + if not root: + return + + if len(result)==level: + result.append(root.val) + + self.helper(root.right,level+1,result) + self.helper(root.left, level+1, result) + +# BFS +class Solution: + def rightSideView(self, root: Optional[TreeNode]) -> List[int]: + res = [] + q = deque([root]) + + while q: + rightSide = None + for i in range(len(q)): + node = q.popleft() + if node: + rightSide=node + if node.left: + q.append(node.left) + if node.right: + q.append(node.right) + + if rightSide: + res.append(rightSide.val) + + return res