3
\$\begingroup\$

Here's my attempt. I iterate through each vertex in the graph and do a DFS to see if I reach back on a vertex I already visited in this vertex's iteration. It seems to work but I am not satisfied with how I short-circuit my code when it found a cycle using if clauses, could not think of a better way to do that.

public boolean isCyclic(Map<T, List<T>> adjacencyList) {
 for (T node: adjacencyList.keySet()) {
 Set<T> visited = new HashSet<>();
 visited.add(node);
 if (isCyclic(visited, node) == true)
 return true;
 }
 return false;
}
private boolean isCyclic(Set<T> visited, T node) {
 boolean retval;
 for (T connectedNode: map.get(node)) {
 if (visited.contains(connectedNode)) {
 // We've reached back to a vertex, i.e. a back-edge
 return true;
 } else {
 visited.add(connectedNode);
 if (isCyclic(visited, connectedNode) == true)
 return true;
 }
 }
 return false;
}
Marc
5,7342 gold badges15 silver badges35 bronze badges
asked Nov 13, 2020 at 5:50
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

I didn't find another way to do it, but I will give you some tips on the current implementation.

Always add curly braces to loop & if

In my opinion, it's a bad practice to have a block of code not surrounded by curly braces; I saw so many bugs in my career related to that, if you forget to add the braces when adding code, you break the logic / semantic of the code.

Simplify the boolean conditions.

In both of the method, you can simplify the boolean validations.

Equivalence

isCyclic(visited, node) == true can be isCyclic(visited, node)

Before

if (isCyclic(visited, node) == true) {
 return true;
}

After

if (isCyclic(visited, node)) {
 return true;
}

Code reduction

In the second method, instead of using the java.util.Set#contains method, you can check the returned boolean of the java.util.Set#add directly; this will allow you to remove an instruction.

Documentation:

Returns:
true if this set did not already contain the specified element

Basic example

Set<Character> set = new java.util.HashSet<>(Set.of('A', 'B', 'C'));
System.out.println(set.add('A')); // false
System.out.println(set.add('D')); // true

This will add the element, if not already present and return true if it was not present.

Before

if (visited.contains(connectedNode)) {
 // We've reached back to a vertex, i.e. a back-edge
 return true;
} else {
 visited.add(connectedNode);
 if (isCyclic(visited, connectedNode)) {
 return true;
 }
}

After

if (!visited.add(connectedNode)) {
 // We've reached back to a vertex, i.e. a back-edge
 return true;
} else {
 if (isCyclic(visited, connectedNode)) {
 return true;
 }
}

In the second method, you can remove the retval variable, since it does nothing.

answered Nov 13, 2020 at 16:34
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Upvoted just for the brackets with for/if part. i introduced so many errors when adding a second statement and forgetting to add the brackets and I swore never to write an if without brackets again. \$\endgroup\$ Commented Nov 13, 2020 at 20:39
  • \$\begingroup\$ Thank you for the handy advice, yes I got lazy about the curlies around the if condition :) \$\endgroup\$ Commented Nov 13, 2020 at 20:49

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.