diff --git a/src/Practice.java b/src/Practice.java index 1dcdfb1..3160f4d 100644 --- a/src/Practice.java +++ b/src/Practice.java @@ -1,6 +1,9 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; public class Practice { @@ -25,7 +28,31 @@ public class Practice { * @return the number of vertices with odd values reachable from the starting vertex */ public static int oddVertices(Vertex starting) { - return 0; + if (starting == null) return 0; + + //initialize visited Set + Set> visited = new HashSet<>(); + + //start recursive traversal with starting vertex + return oddVerticesHelper(starting, visited); + } + //helper method- + //no extra shared mutable variables needed—recursion handles + //accumulation through returns + private static int oddVerticesHelper(Vertex current, Set> visited) { + //base case-if we've already visited this vertex return immediately + if(visited.contains(current)) return 0; + //mark current as visited to avoid infinite loops + visited.add(current); + //count this vertex.data if odd + int count = (current.data % 2 != 0) ? 1 : 0; + //for-each iterates each neighbor of current + for (Vertex neighbor : current.neighbors) { + //recursion step adds up counts returned from neighbors + count += oddVerticesHelper(neighbor, visited); + } + //return total count accumulated from this vertex downward + return count; } /** @@ -48,7 +75,28 @@ public static int oddVertices(Vertex starting) { */ public static List sortedReachable(Vertex starting) { // Unimplemented: perform a depth-first search and sort the collected values. - return null; + //base case + if (starting == null) return new ArrayList<>(); + //initialize empty visited Set/empty results List + Set> visited = new HashSet<>(); + List results = new ArrayList<>(); + // + sortedReachableHelper(starting, visited, results); + //sort results List into asc order + Collections.sort(results); + return results; + } + private static void sortedReachableHelper(Vertex current, Set> visited, List results) { + //base case + if (visited.contains(current)) return; + //add current and current.data to visited and results trackers + visited.add(current); + results.add(current.data); + //for each to iterate through each neighbor of current + for (Vertex neighbor : current.neighbors) { + //recurse all neighbors + sortedReachableHelper(neighbor, visited, results); + } } /** @@ -57,14 +105,37 @@ public static List sortedReachable(Vertex starting) { * It is assumed that there are no duplicate vertices. * If the starting vertex is not present as a key in the map, returns an empty list. * - * @param graph a map representing the graph + * @param graph a map representing the adjacency list of the graph * @param starting the starting vertex value * @return a sorted list of all reachable vertex values */ public static List sortedReachable(Map> graph, int starting) { - return null; + //base case ( more generic: return Collections.emptySet(); ) + if (graph == null || !graph.containsKey(starting)) return new ArrayList<>(); + //instantiate visited Set + Set visited = new HashSet<>(); + + sortedReachableHelper(graph, starting, visited); + + //convert visited data into List format + List sorted = new ArrayList<>(visited); + //sort newly formed List + Collections.sort(sorted); + //return List of sorted reachable 'vertices' + return sorted; } + private static void sortedReachableHelper(Map> graph, int current, Set visited) { + //base case - if we've been here already then return immediately + if (visited.contains(current)) return; + //add current to visited + visited.add(current); + //for each avoids getting a null pointer exception or needing + //an extra check for null values explicitly + for (Integer neighbor : graph.getOrDefault(current, Collections.emptySet())) { //recursively transverse to fill up visited Set + sortedReachableHelper(graph, neighbor, visited); + } + } /** * Returns true if and only if it is possible both to reach v2 from v1 and to reach v1 from v2. * A vertex is always considered reachable from itself. @@ -80,6 +151,29 @@ public static List sortedReachable(Map> graph, in * @return true if there is a two-way connection between v1 and v2, false otherwise */ public static boolean twoWay(Vertex v1, Vertex v2) { + //base case + if (v1 == null || v2 == null) return false; + //instantiate Set inside helper method + //call helper method + boolean oneWay = twoWayHelper(v1, v2, new HashSet<>()); + //repeat for opposite direction + + //call helper method + boolean otherWay = twoWayHelper(v2, v1, new HashSet<>()); + return oneWay && otherWay; + } + private static boolean twoWayHelper(Vertex current, Vertex v2, Set> visited) { + //base case -> successfully reached target vertex + if (current == v2) return true; + //already visited? stop recursion! + if (visited.contains(current)) return false; + //add current to visited to avoid looping + visited.add(current); + //for each iterate all neighbors of current + for (Vertex neighbor : current.neighbors) { + //recursively transverse each neighbor of current + if (twoWayHelper(neighbor, v2, visited)) return true; + } return false; } @@ -96,6 +190,22 @@ public static boolean twoWay(Vertex v1, Vertex v2) { * @return whether there exists a valid positive path from starting to ending */ public static boolean positivePathExists(Map> graph, int starting, int ending) { + //base case + if (starting < 0 || ending < 0 || graph == null || !graph.containsKey(starting) || !graph.containsKey(ending)) return false; + //call helper method inside boolean solution return + return positivePathExistsHelper(graph, starting, ending, new HashSet<>()); + } + private static boolean positivePathExistsHelper(Map> graph, int current, int ending, Set visited) { + //base case -> have we reached ending via current? + if (current == ending) return true; + //have we been here already? if so return false + if (visited.contains(current)) return false; + //add current to visited as tracking to avoid looping + visited.add(current); + //for each to iterate neighbors of current + for (Integer neighbor : graph.getOrDefault(current, Collections.emptySet())) { + if (neighbor > 0 && positivePathExistsHelper(graph, neighbor, ending, visited)) return true; + } return false; } @@ -109,6 +219,27 @@ public static boolean positivePathExists(Map> graph, int s * @return true if a person in the extended network works at the specified company, false otherwise */ public static boolean hasExtendedConnectionAtCompany(Professional person, String companyName) { + //base case + if (person == null) return false; + //call helper + return hasExtendedConnectionAtCompanyHelper(person, companyName, new HashSet<>()); + } + private static boolean hasExtendedConnectionAtCompanyHelper(Professional currentPerson, String companyName, Set visited) { + //base case: if we've reached via DFS a person + //working at same company as starting person + //return true; **use .equals() for String comparisons + if (currentPerson.getCompany().equals(companyName)) return true; + //have we visited this person already? return false! + if (visited.contains(currentPerson)) return false; + //add currentPerson to visited Set + visited.add(currentPerson); + //for-each iterates all connections currentPerson has + for (Professional connection : currentPerson.getConnections()) { + //if recursion step is true, return true + if (hasExtendedConnectionAtCompanyHelper(connection, companyName, visited)) { + return true; + } + } return false; } }