Cracking the Coding Interview - 4.1 Graph Traversal

Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
0
down vote
favorite
I'm working through the classic Cracking the Coding Interview book. I'm trying to solve the following graph problem:
4.1) Route Between Nodes: Given a directed graph, design an algorithm to find out whether there is a route between two nodes.
I've written a solution in JavaScript and found it was a lot less complicated than the book's solution. Am I missing something? Why does the solution use a Visiting state? Can't we just use Visited instead?
function RouteBetweenNodes( node1, node2 )
const q = new Queue()
q.add( node1 )
while ( !q.isEmpty() )
const node = q.remove()
if ( node === node2 )
return true
node.visited = true
node.children.forEach( child => !child.visited && q.add( child ) )
return false
Here is an implementation of a Queue for completeness:
class QueueNode
constructor( data )
this.data = data
this.next = null
class Queue
constructor()
this.first = null
this.last = null
add( item )
const newNode = new QueueNode( item )
if ( this.last )
this.last.next = newNode
else
this.first = newNode
this.last = newNode
remove()
if ( this.first )
const data = this.first.data
this.first = this.first.next
if ( this.first == null )
this.last == null
return data
throw Error( 'empty queue' )
peek()
if ( this.first )
return this.first.data
throw Error( 'empty queue' )
isEmpty()
return this.first === null
Here is the book's solution.
javascript algorithm graph
 |Â
show 4 more comments
up vote
0
down vote
favorite
I'm working through the classic Cracking the Coding Interview book. I'm trying to solve the following graph problem:
4.1) Route Between Nodes: Given a directed graph, design an algorithm to find out whether there is a route between two nodes.
I've written a solution in JavaScript and found it was a lot less complicated than the book's solution. Am I missing something? Why does the solution use a Visiting state? Can't we just use Visited instead?
function RouteBetweenNodes( node1, node2 )
const q = new Queue()
q.add( node1 )
while ( !q.isEmpty() )
const node = q.remove()
if ( node === node2 )
return true
node.visited = true
node.children.forEach( child => !child.visited && q.add( child ) )
return false
Here is an implementation of a Queue for completeness:
class QueueNode
constructor( data )
this.data = data
this.next = null
class Queue
constructor()
this.first = null
this.last = null
add( item )
const newNode = new QueueNode( item )
if ( this.last )
this.last.next = newNode
else
this.first = newNode
this.last = newNode
remove()
if ( this.first )
const data = this.first.data
this.first = this.first.next
if ( this.first == null )
this.last == null
return data
throw Error( 'empty queue' )
peek()
if ( this.first )
return this.first.data
throw Error( 'empty queue' )
isEmpty()
return this.first === null
Here is the book's solution.
javascript algorithm graph
1
Welcome to Code Review! I hope you get some good answers =)
â Phrancis
Jun 26 at 22:07
TheVisitingstate lets you tell apart nodes waiting in the queue from the truly uncharted nodes. Without such state the same node may be added multiple times. It hurts performance, and in some (very contrived) cases may even lead to incorrectness.
â vnp
Jun 26 at 22:24
@vnp I can't see a case where it would lead to incorrect results. Can you elaborate?
â hoffmale
Jun 26 at 22:32
@hoffmale On a specially crafted infinite graph, with some nodes having infinitely many inbound edges, the algorithm would fail to find a surely existing path, whereas a book solution would succeed. Pretty contrived, as I said.
â vnp
Jun 26 at 22:38
It appears that the code in the image is Java, but your code is Javascript (or at least you used the tag javascript)... is that intentional?
â Sam Onela
Jun 26 at 22:40
 |Â
show 4 more comments
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I'm working through the classic Cracking the Coding Interview book. I'm trying to solve the following graph problem:
4.1) Route Between Nodes: Given a directed graph, design an algorithm to find out whether there is a route between two nodes.
I've written a solution in JavaScript and found it was a lot less complicated than the book's solution. Am I missing something? Why does the solution use a Visiting state? Can't we just use Visited instead?
function RouteBetweenNodes( node1, node2 )
const q = new Queue()
q.add( node1 )
while ( !q.isEmpty() )
const node = q.remove()
if ( node === node2 )
return true
node.visited = true
node.children.forEach( child => !child.visited && q.add( child ) )
return false
Here is an implementation of a Queue for completeness:
class QueueNode
constructor( data )
this.data = data
this.next = null
class Queue
constructor()
this.first = null
this.last = null
add( item )
const newNode = new QueueNode( item )
if ( this.last )
this.last.next = newNode
else
this.first = newNode
this.last = newNode
remove()
if ( this.first )
const data = this.first.data
this.first = this.first.next
if ( this.first == null )
this.last == null
return data
throw Error( 'empty queue' )
peek()
if ( this.first )
return this.first.data
throw Error( 'empty queue' )
isEmpty()
return this.first === null
Here is the book's solution.
javascript algorithm graph
I'm working through the classic Cracking the Coding Interview book. I'm trying to solve the following graph problem:
4.1) Route Between Nodes: Given a directed graph, design an algorithm to find out whether there is a route between two nodes.
I've written a solution in JavaScript and found it was a lot less complicated than the book's solution. Am I missing something? Why does the solution use a Visiting state? Can't we just use Visited instead?
function RouteBetweenNodes( node1, node2 )
const q = new Queue()
q.add( node1 )
while ( !q.isEmpty() )
const node = q.remove()
if ( node === node2 )
return true
node.visited = true
node.children.forEach( child => !child.visited && q.add( child ) )
return false
Here is an implementation of a Queue for completeness:
class QueueNode
constructor( data )
this.data = data
this.next = null
class Queue
constructor()
this.first = null
this.last = null
add( item )
const newNode = new QueueNode( item )
if ( this.last )
this.last.next = newNode
else
this.first = newNode
this.last = newNode
remove()
if ( this.first )
const data = this.first.data
this.first = this.first.next
if ( this.first == null )
this.last == null
return data
throw Error( 'empty queue' )
peek()
if ( this.first )
return this.first.data
throw Error( 'empty queue' )
isEmpty()
return this.first === null
Here is the book's solution.
javascript algorithm graph
edited Jun 27 at 3:43
asked Jun 26 at 21:51
Narin Luangrath
63
63
1
Welcome to Code Review! I hope you get some good answers =)
â Phrancis
Jun 26 at 22:07
TheVisitingstate lets you tell apart nodes waiting in the queue from the truly uncharted nodes. Without such state the same node may be added multiple times. It hurts performance, and in some (very contrived) cases may even lead to incorrectness.
â vnp
Jun 26 at 22:24
@vnp I can't see a case where it would lead to incorrect results. Can you elaborate?
â hoffmale
Jun 26 at 22:32
@hoffmale On a specially crafted infinite graph, with some nodes having infinitely many inbound edges, the algorithm would fail to find a surely existing path, whereas a book solution would succeed. Pretty contrived, as I said.
â vnp
Jun 26 at 22:38
It appears that the code in the image is Java, but your code is Javascript (or at least you used the tag javascript)... is that intentional?
â Sam Onela
Jun 26 at 22:40
 |Â
show 4 more comments
1
Welcome to Code Review! I hope you get some good answers =)
â Phrancis
Jun 26 at 22:07
TheVisitingstate lets you tell apart nodes waiting in the queue from the truly uncharted nodes. Without such state the same node may be added multiple times. It hurts performance, and in some (very contrived) cases may even lead to incorrectness.
â vnp
Jun 26 at 22:24
@vnp I can't see a case where it would lead to incorrect results. Can you elaborate?
â hoffmale
Jun 26 at 22:32
@hoffmale On a specially crafted infinite graph, with some nodes having infinitely many inbound edges, the algorithm would fail to find a surely existing path, whereas a book solution would succeed. Pretty contrived, as I said.
â vnp
Jun 26 at 22:38
It appears that the code in the image is Java, but your code is Javascript (or at least you used the tag javascript)... is that intentional?
â Sam Onela
Jun 26 at 22:40
1
1
Welcome to Code Review! I hope you get some good answers =)
â Phrancis
Jun 26 at 22:07
Welcome to Code Review! I hope you get some good answers =)
â Phrancis
Jun 26 at 22:07
The
Visiting state lets you tell apart nodes waiting in the queue from the truly uncharted nodes. Without such state the same node may be added multiple times. It hurts performance, and in some (very contrived) cases may even lead to incorrectness.â vnp
Jun 26 at 22:24
The
Visiting state lets you tell apart nodes waiting in the queue from the truly uncharted nodes. Without such state the same node may be added multiple times. It hurts performance, and in some (very contrived) cases may even lead to incorrectness.â vnp
Jun 26 at 22:24
@vnp I can't see a case where it would lead to incorrect results. Can you elaborate?
â hoffmale
Jun 26 at 22:32
@vnp I can't see a case where it would lead to incorrect results. Can you elaborate?
â hoffmale
Jun 26 at 22:32
@hoffmale On a specially crafted infinite graph, with some nodes having infinitely many inbound edges, the algorithm would fail to find a surely existing path, whereas a book solution would succeed. Pretty contrived, as I said.
â vnp
Jun 26 at 22:38
@hoffmale On a specially crafted infinite graph, with some nodes having infinitely many inbound edges, the algorithm would fail to find a surely existing path, whereas a book solution would succeed. Pretty contrived, as I said.
â vnp
Jun 26 at 22:38
It appears that the code in the image is Java, but your code is Javascript (or at least you used the tag javascript)... is that intentional?
â Sam Onela
Jun 26 at 22:40
It appears that the code in the image is Java, but your code is Javascript (or at least you used the tag javascript)... is that intentional?
â Sam Onela
Jun 26 at 22:40
 |Â
show 4 more comments
1 Answer
1
active
oldest
votes
up vote
1
down vote
accepted
Your worst case performance (every node is connected to each other node but
node2) is $mathcalO(n^2)$, up from the "normal" $mathcalO(n)$, because nodes can be added to the queue multiple times. This should also increase the average runtime. This gets even worse if multiple edges between any 2 nodes are allowed.Note that adding another check
q.contains(node)would still result in a runtime of $mathcalO(n^2)$ as those checks add a factor of $mathcalO(n)$. TheVisitingstate prevents this.visitedis never reset tofalse(in the presented code). This will lead to errors in subsequent calls.The definition of
Queueis missing.
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
Your worst case performance (every node is connected to each other node but
node2) is $mathcalO(n^2)$, up from the "normal" $mathcalO(n)$, because nodes can be added to the queue multiple times. This should also increase the average runtime. This gets even worse if multiple edges between any 2 nodes are allowed.Note that adding another check
q.contains(node)would still result in a runtime of $mathcalO(n^2)$ as those checks add a factor of $mathcalO(n)$. TheVisitingstate prevents this.visitedis never reset tofalse(in the presented code). This will lead to errors in subsequent calls.The definition of
Queueis missing.
add a comment |Â
up vote
1
down vote
accepted
Your worst case performance (every node is connected to each other node but
node2) is $mathcalO(n^2)$, up from the "normal" $mathcalO(n)$, because nodes can be added to the queue multiple times. This should also increase the average runtime. This gets even worse if multiple edges between any 2 nodes are allowed.Note that adding another check
q.contains(node)would still result in a runtime of $mathcalO(n^2)$ as those checks add a factor of $mathcalO(n)$. TheVisitingstate prevents this.visitedis never reset tofalse(in the presented code). This will lead to errors in subsequent calls.The definition of
Queueis missing.
add a comment |Â
up vote
1
down vote
accepted
up vote
1
down vote
accepted
Your worst case performance (every node is connected to each other node but
node2) is $mathcalO(n^2)$, up from the "normal" $mathcalO(n)$, because nodes can be added to the queue multiple times. This should also increase the average runtime. This gets even worse if multiple edges between any 2 nodes are allowed.Note that adding another check
q.contains(node)would still result in a runtime of $mathcalO(n^2)$ as those checks add a factor of $mathcalO(n)$. TheVisitingstate prevents this.visitedis never reset tofalse(in the presented code). This will lead to errors in subsequent calls.The definition of
Queueis missing.
Your worst case performance (every node is connected to each other node but
node2) is $mathcalO(n^2)$, up from the "normal" $mathcalO(n)$, because nodes can be added to the queue multiple times. This should also increase the average runtime. This gets even worse if multiple edges between any 2 nodes are allowed.Note that adding another check
q.contains(node)would still result in a runtime of $mathcalO(n^2)$ as those checks add a factor of $mathcalO(n)$. TheVisitingstate prevents this.visitedis never reset tofalse(in the presented code). This will lead to errors in subsequent calls.The definition of
Queueis missing.
edited Jun 26 at 22:57
answered Jun 26 at 22:24
hoffmale
4,225630
4,225630
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f197314%2fcracking-the-coding-interview-4-1-graph-traversal%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
1
Welcome to Code Review! I hope you get some good answers =)
â Phrancis
Jun 26 at 22:07
The
Visitingstate lets you tell apart nodes waiting in the queue from the truly uncharted nodes. Without such state the same node may be added multiple times. It hurts performance, and in some (very contrived) cases may even lead to incorrectness.â vnp
Jun 26 at 22:24
@vnp I can't see a case where it would lead to incorrect results. Can you elaborate?
â hoffmale
Jun 26 at 22:32
@hoffmale On a specially crafted infinite graph, with some nodes having infinitely many inbound edges, the algorithm would fail to find a surely existing path, whereas a book solution would succeed. Pretty contrived, as I said.
â vnp
Jun 26 at 22:38
It appears that the code in the image is Java, but your code is Javascript (or at least you used the tag javascript)... is that intentional?
â Sam Onela
Jun 26 at 22:40