Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions BinaryTreeLevelOrderTraversal_usingBFS.java
Original file line number Diff line number Diff line change
@@ -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<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();

if (root == null) return result;

Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);

while (!queue.isEmpty()) {
int size = queue.size();
List<Integer> list = new ArrayList<>();
for (int i=0; i<size; i++) {
TreeNode node = queue.poll();

list.add(node.val);

if (node.left != null) {
queue.offer(node.left);
}

if (node.right != null) {
queue.offer(node.right);
}
}
result.add(list);
}

return result;
}
}
54 changes: 54 additions & 0 deletions BinaryTreeLevelOrderTraversal_usingDFS.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Time Complexity : O(n) as we have to visit all nodes in order to get the node at each level
// Space Complexity : O(h) as the recursive stack can take that much space but in the worst case it will be O(n)
// Did this code successfully run on Leetcode : yes
// Any problem you faced while coding this : no

/*
* Problem: Binary Tree Level Order Traversal
* */

/*
* Approach: Using Depth First Search
* In this approach, we use dfs approach. We start from the root node and visit its children in the dfs manner.
* Since, at every level we want to know what level we are at, we must maintain a level and the result list
* as the parameters of recursion. We increment the level, as we go one step deep into the recursion. At every
* level we check if there is a list initiated for that level, if not we declare one and start adding the node values
* at every level for the corresponding list for a specific level.
* */

import java.util.ArrayList;
import java.util.List;
import TreeNode;

public class BinaryTreeLevelOrderTraversal_usingDFS {
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_usingDFS binaryTreeLevelOrderTraversalUsingDFS = new BinaryTreeLevelOrderTraversal_usingDFS();
System.out.println(binaryTreeLevelOrderTraversalUsingDFS.levelOrder(root));
}

public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
helper(root, 0, result);
return result;
}

public void helper(TreeNode root, int level, List<List<Integer>> 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);
}
}
76 changes: 76 additions & 0 deletions CourseSchedule_usingDFS.java
Original file line number Diff line number Diff line change
@@ -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<Integer, List<Integer>> map;
public boolean canFinish(int numCourses, int[][] prerequisites) {
this.map = new HashMap<>();

for (int i=0; i<numCourses; i++) {
map.put(i, new ArrayList<>());
}

for (int[] prereq: prerequisites) {
int dep = prereq[0];
int ind = prereq[1];

map.get(ind).add(dep);
}

Set<Integer> visited = new HashSet<>();
Set<Integer> inStack = new HashSet<>();
for (int i=0; i<numCourses; i++) {
if (!dfsHelper(i, visited, inStack)) return false;
}

return true;
}

public boolean dfsHelper(Integer course, Set<Integer> visited, Set<Integer> inStack) {
if (inStack.contains(course)) {
return false;
}

if (visited.contains(course)) {
return true;
}

visited.add(course);
inStack.add(course);
List<Integer> children = map.get(course);

for (Integer child: children) {
if (!dfsHelper(child, visited, inStack)) return false;
}

inStack.remove(course);

return true;
}
}
76 changes: 76 additions & 0 deletions CourseSchedule_usingTopologicalSort.java
Original file line number Diff line number Diff line change
@@ -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<Integer, List<Integer>> 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<Integer> queue = new LinkedList<>();
for (int i=0; i<indegree.length; i++) {
if (indegree[i] == 0) {
queue.offer(i);
count++;
}
}

while (!queue.isEmpty()) {
Integer node = queue.poll();

List<Integer> 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;
}
}
15 changes: 15 additions & 0 deletions TreeNode.java
Original file line number Diff line number Diff line change
@@ -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;
}
}