Skip to content

Commit

Permalink
Loop detection in linked lists.
Browse files Browse the repository at this point in the history
  • Loading branch information
pfcoperez committed Feb 16, 2018
1 parent 724a7e5 commit 3a30f35
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,33 @@ package object directed {
def apply[T](v: T, lazyNext: => Node[T]): Node[T] = new Node(Some(v), Some(lazyNext))
def apply[T](v: T): Node[T] = new Node[T](Some(v), None)
}

/**
* Detects loops in a Linked list providing their first node if found
* O(n), n = number of elements in the list
*
* @param list Linked list
* @return `Some(First node in the loop)` if found, `None` otherwise
*/
def detectLoop[T](list: Node[T]): Option[Node[T]] = {

def race(slow: Node[T], fast: Node[T], firstIteration: Boolean): Option[Node[T]] =
if(!firstIteration && slow == fast) Some(slow)
else {
val maybeNextStep = for {
nextSlow <- slow.maybeNext
fastNext <- fast.maybeNext
nextFast <- fastNext.maybeNext
} yield (nextSlow, nextFast)
maybeNextStep match { //Just a map, pattern match to keep tail recursion
case Some((nextSlow, nextFast)) => race(nextSlow, nextFast, false)
case _ => None
}
}

race(list, list, true)
}

}

}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.pfcoperez.dailyalgorithm.datastructures.graphs.directed

import org.scalatest.{Matchers, WordSpec}
import LinkedStructures.TyingTheNot.{detectLoop, Node => TNode}

class TyingTheNotSpec extends WordSpec with Matchers {

"TyingTheNot linked list implementation" when {

"presenting loops" should {

"expose them through `detectLoop`" in {

val linkedWithLoop = {
lazy val header = TNode(1, TNode(2, tail))
lazy val tail: TNode[Int] = TNode(3, header)
header
}

detectLoop(linkedWithLoop) shouldBe Some(linkedWithLoop)

}

"not detect false loops" in {

val linkedList = TNode(1, TNode(2, TNode(3, TNode(4))))

detectLoop(linkedList) shouldBe None
}

}

}

}

0 comments on commit 3a30f35

Please sign in to comment.