Golang program to detect a loop in linked list



In Golang data structures, a linked list is the one that contains nodes which contains two fields: a next pointer and the data of the list. We will use two methods to detect a loop in linked list. In the first method two-pointer approach will be used and in the second example maps are used to execute the program. Let’s go through those examples to understand the execution.

Method 1: Using two-pointer approach

In this method, the linked list is traversed using a low pointer and a high pointer. While the high pointer advances two steps at a time, the low pointer advances one step at a time. The high pointer will eventually overtake the low pointer if the linked list contains a loop, and they will both be pointing at the same node. Given that the linked list contains a loop in this instance, we return true.

Algorithm

  • Step 1 − Create a package main and declare fmt(format package) package in the program where main produces executable codes and fmt helps in formatting input and output.

  • Step 2 − Create a Node struct with value of type int and Next of type Node.

  • Step 3 − Create a function has_loop and in that function make two pointers—low and high—and set them both to point to the linked list's head.

  • Step 4 − The high pointer moves two steps at a time, whereas the low pointer moves one step at a time.

  • Step 5 − The high pointer will eventually overtake the low pointer in a linked list with a loop, and both points will then point to the same node.

  • Step 6 − Return true in this situation since the linked list contains a loop.

  • Step 7 − The fast pointer will eventually reach the end of the linked list if there is no loop, in which case we can return false.

  • Step 8 − The print statement is executed using fmt.Println() function where ln means new line.

  • Step 9 − The "two-pointer strategy" or "hare and tortoise algorithm" are other names for this formula. Given that there are only two pointers needed, it has an O(1) space complexity and an O(n) time complexity, where n is the number of nodes in the linked list.

Example

In this example we will use two pointer approach to execute the program.

package main
import "fmt"

type Node struct {
   Value int
   Next  *Node
}

func has_loop(head *Node) bool {
   low := head
   high := head
   for high != nil && high.Next != nil {
      low = low.Next
      high = high.Next.Next
      if low == high {
         return true
      }
   }
   return false
}

func main() {
   head := &Node{Value: 1} //initialize the linked list with values
   node2 := &Node{Value: 2}
   node3 := &Node{Value: 3}
   node4 := &Node{Value: 4}
   
   head.Next = node2 //point to the elements using linked list
   node2.Next = node3
   node3.Next = node4
   node4.Next = node2
   
   fmt.Println("Does this linked list has loop?")
   fmt.Println(has_loop(head)) // Output: true
}

Output

Does this linked list has loop?
true

Method 2: Using Maps in Golang

The visited nodes are recorded on a map in this implementation. We determine if a node in the linked list has been visited previously for each node inside. If it has, we return true since the linked list contains a loop. We return false if we reach the end of the linked list without running into a visited node.

Algorithm

  • Step 1 − Create a package main and declare fmt(format package) package in the program where main produces executable codes and fmt helps in formatting input and output.

  • Step 2 − Create a Node struct with value of type int and Next of type Node.

  • Step 3 − Create a function has_loop and in that function make a map to store the nodes you've visited.

  • Step 4 − Check each node as you move through the linked list, starting at the head.

  • Step 5 − Verify each node's presence on the map to see if it has been visited previously.

  • Step 6 − Return true if a node has been visited previously because the linked list has a loop.

  • Step 7 − Return false if there are no visited nodes at the end of the linked list when we reach it.

  • Step 8 − This approach employs a map to store the visited nodes, which results in a time complexity of O(n) and a space complexity of O(n), where n is the number of nodes in the linked list.

Example

In this example we will use maps to store visited nodes.

package main
import "fmt"

type Node struct {
   Value int
   Next  *Node
}

func has_loop(head *Node) bool {
   Map := make(map[*Node]bool)  //create a map to store visited nodes.
   for current := head; current != nil; current = current.Next {
      if Map[current] {
         return true
      }
      Map[current] = true
   }
   return false
}

func main() {
   head := &Node{Value: 10}   //fill the linked list with elements 
   node2 := &Node{Value: 20}
   node3 := &Node{Value: 30}
   node4 := &Node{Value: 40}
   
   head.Next = node2 
   node2.Next = node3
   node3.Next = node4
   node4.Next = node2
   fmt.Println("Does this linked list has loop?")
   
   fmt.Println(has_loop(head)) // Output: true
}

Output

Does this linked list has loop?
true

Conclusion

We executed the program of detecting whether there is a loop in linked list or not using two methods. In the first method we used two-pointer approach and in the second example we used maps to store visited nodes.


Advertisements