diff --git a/BinaryTreeLevelOrderTraversal_usingBFS.java b/BinaryTreeLevelOrderTraversal_usingBFS.java new file mode 100644 index 00000000..1b14f186 --- /dev/null +++ b/BinaryTreeLevelOrderTraversal_usingBFS.java @@ -0,0 +1,66 @@ +// Time Complexity : O(n) as we have to visit all the nodes at all levels +// Space Complexity : O(n) as we use a queue to store nodes at each level +// Did this code successfully run on Leetcode : yes +// Any problem you faced while coding this : no + +/* + * Problem: Binary Tree Level Order Traversal + * */ + +/* + * Approach: Using Breadth First Search + * In this approach, we use breadth first search starting from the root nodes by storing them in a queue. Every time + * we pop a node from the queue, we process it and store their children in the queue. At every subsequent level, + * we do not know how many nodes we should be popping which is why we use a size variable to do that. + * We keep processing each level and all nodes belonging to one level in a list. Once, we are done processing the level, + * we can add this list to the result list. We keep doing it until the queue is empty. + * */ + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; +import TreeNode; + +public class BinaryTreeLevelOrderTraversal_usingBFS { + public static void main(String[] args) { + TreeNode root = new TreeNode(3); + root.left = new TreeNode(9); + root.right = new TreeNode(20); + root.right.left = new TreeNode(15); + root.right.right = new TreeNode(7); + + BinaryTreeLevelOrderTraversal_usingBFS binaryTreeLevelOrderTraversalUsingBFS = new BinaryTreeLevelOrderTraversal_usingBFS(); + System.out.println(binaryTreeLevelOrderTraversalUsingBFS.levelOrder(root)); + } + + public List> levelOrder(TreeNode root) { + List> result = new ArrayList<>(); + + if (root == null) return result; + + Queue queue = new LinkedList<>(); + queue.offer(root); + + while (!queue.isEmpty()) { + int size = queue.size(); + List list = new ArrayList<>(); + for (int i=0; i> levelOrder(TreeNode root) { + List> result = new ArrayList<>(); + helper(root, 0, result); + return result; + } + + public void helper(TreeNode root, int level, List> result) { + // base case + if(root == null) return; + + // logic + if (level == result.size()) { + result.add(new ArrayList<>()); + } + + result.get(level).add(root.val); + helper(root.left, level+1, result); + helper(root.right, level+1, result); + } +} diff --git a/CourseSchedule_usingDFS.java b/CourseSchedule_usingDFS.java new file mode 100644 index 00000000..514d8cef --- /dev/null +++ b/CourseSchedule_usingDFS.java @@ -0,0 +1,76 @@ +// Time Complexity : O(v+e) where v is the number of courses(vertices) and e is the number of prereqs(edges) +// Space Complexity : O(v+e) where v is the number of courses(vertices) and e is the number of prereqs(edges) +// The graph map, hashsets and recursive stack take up v+e space +// Did this code successfully run on Leetcode : yes +// Any problem you faced while coding this : no + +/* + * Problem: Course Schedule 1 + * */ + +/* + * Approach: Using Depth First Search + * In this approach, we use DFS for finding if we can complete all courses at a time. We create an adjacency list/map + * for mapping the relationships between the courses. We maintain the visited and inStack to keep a track of the visited + * nodes and to keep a track of visited nodes in a recursive path. If a node is already added to the inStack set, + * it would mean that the current path is running into a cycle and there is an interdependency. + * */ + +import java.util.*; +import TreeNode; + +public class CourseSchedule_usingDFS { + public static void main(String[] args) { + int numCourses = 5; + int[][] prerequisites = {{1,4},{2,4},{3,1},{3,2}}; + + CourseSchedule_usingDFS courseScheduleUsingDFS = new CourseSchedule_usingDFS(); + System.out.println(courseScheduleUsingDFS.canFinish(numCourses, prerequisites)); + } + + Map> map; + public boolean canFinish(int numCourses, int[][] prerequisites) { + this.map = new HashMap<>(); + + for (int i=0; i()); + } + + for (int[] prereq: prerequisites) { + int dep = prereq[0]; + int ind = prereq[1]; + + map.get(ind).add(dep); + } + + Set visited = new HashSet<>(); + Set inStack = new HashSet<>(); + for (int i=0; i visited, Set inStack) { + if (inStack.contains(course)) { + return false; + } + + if (visited.contains(course)) { + return true; + } + + visited.add(course); + inStack.add(course); + List children = map.get(course); + + for (Integer child: children) { + if (!dfsHelper(child, visited, inStack)) return false; + } + + inStack.remove(course); + + return true; + } +} diff --git a/CourseSchedule_usingTopologicalSort.java b/CourseSchedule_usingTopologicalSort.java new file mode 100644 index 00000000..6935fdec --- /dev/null +++ b/CourseSchedule_usingTopologicalSort.java @@ -0,0 +1,76 @@ +// Time Complexity : O(v+e) where v is the number of courses(vertices) and e is the number of prereqs(edges) +// Space Complexity : O(v+e) where v is the number of courses(vertices) and e is the number of prereqs(edges) +// The graph map, indegree and queue take up v+e space +// Did this code successfully run on Leetcode : yes +// Any problem you faced while coding this : no + +/* + * Problem: Course Schedule 1 + * */ + +/* + * Approach: Using Topological sort + * In this approach, we do a topological sort on the indegree relationships formed by the courses and their prereqs. + * We process the courses which do not have any dependencies by adding them to a queue. We then starting popping every + * course from the queue and process their children. While processing their children, we reduce one dependency and check + * if they are independent, if yes we add them to the queue. + * + * It is important that we start by adding ALL independent courses in the beginning to the queue. + * */ + +import java.util.*; +import TreeNode; + +public class CourseSchedule_usingTopologicalSort { + public static void main(String[] args) { + int numCourses = 5; + int[][] prerequisites = {{1,4},{2,4},{3,1},{3,2}}; + + CourseSchedule_usingTopologicalSort courseScheduleUsingTopologicalSort = new CourseSchedule_usingTopologicalSort(); + System.out.println(courseScheduleUsingTopologicalSort.canFinish(numCourses, prerequisites)); + } + + public boolean canFinish(int numCourses, int[][] prerequisites) { + Map> map = new HashMap<>(); + int[] indegree = new int[numCourses]; + + for (int[] prereq: prerequisites) { + int dep = prereq[0]; + int ind = prereq[1]; + + if (!map.containsKey(ind)) { + map.put(ind, new ArrayList<>()); + } + + map.get(ind).add(dep); + indegree[dep]++; + } + + int count = 0; + Queue queue = new LinkedList<>(); + for (int i=0; i children = map.get(node); + + if (children == null) continue; + + for (Integer child: children) { + indegree[child]--; + if (indegree[child] == 0) { + count++; + queue.offer(child); + } + } + } + + return count == numCourses; + } +} diff --git a/TreeNode.java b/TreeNode.java new file mode 100644 index 00000000..6e0f3501 --- /dev/null +++ b/TreeNode.java @@ -0,0 +1,15 @@ +public class TreeNode { + int val; + TreeNode left; + TreeNode right; + + TreeNode() {} + + TreeNode(int val) {this.val = val;} + + TreeNode(int val, TreeNode left, TreeNode right) { + this.val = val; + this.left = left; + this.right = right; + } +} \ No newline at end of file