Sabtu, 19 Juli 2014

How to Find if Linked List contains Loops or Cycles in Java - Coding Question




Write a Java program to check if a linked list is circular or cyclic,  and how do you find if a linked list contains
loop or cycles in Java are some common linked list related data structure interview questions
asked in various Java Interviews. This is some time asked as follow-up question
of basic linked list questions like inserting element at beginning, middle and
end of linked list or finding length of linked list.
In o
rder to solve linked list related algorithmic question in Java, you need to
be familiar with concept of singly linked list, doubly linked list and circular
linked list. Until stated specifically, most questions are based on singly
linked list. For those who are not familiar of linked list data structure, its
a collection of nodes. Each node contains two parts data and address, where
address part points to another node in linked list. Last node of linked list,
often referred as tail points to null. Also a singly list can only move in one
direction, towards end. Now, let's come back to this question. Good thing about
this question is that, it can also be solved by using two pointer approach
discussed in How to find middle element of linked list
in single pass
. If a lin
ked list contains a loop or cycle it is
known as circular or cyclic linked list. As I said we can use two pointer
approach to check if a linked list is circular or not.







Algorithm to find if linked list contains
loops or cycles



Two pointers, fast and slow is used
while iterating over linked list. Fast pointer moves two nodes in each
iteration, while slow pointer moves to one node. If linked list contains loop
or cycle than both fast and slow pointer will meet at some point during
iteration. If they don't meet and fast or slow will point to null, then linked
list is not cyclic and it doesn't contain any loop. Here is exact algorithm





1) Use two pointers fast and slow


2) Move fast two nodes and slow one node in each iteration


3) If fast and slow meet then linked list contains cycle


4) if fast points to null or fast.next points to null then linked list is
not cyclic





Next section contains Java program to check if linked list contains loop
or cycle, which is exact implementation of above algorithm. This algorithm is
also known as Floyd’s cycle finding algorithm
a
nd popularly known as tortoise and hare algorithm to find cycles in linked
list.





Java program to check if linked list is circular or not.



This Java program uses LinkedList(not java.util.LinkedList)  and Node class from
previous example of Linked List, with modification of adding toString() method and
appendToTail() method.
Also,
isCyclic() method of linked list is used to implement logic to
find if linked list contains cycle or not. Subsequently
isCyclic() returns true if linked
list is cyclic otherwise it return
false.



/*
* Java class to represent linked list data structure.
*/

public class LinkedList {
private Node head;
public LinkedList() { this.head = new Node("head"); }
public Node head() { return head;}

public void appendIntoTail(Node node) {
Node current = head;

//find last element of LinkedList i.e. tail
while(current.next() != null){
current = current.next();
}
//appending new node to tail in LinkedList
current.setNext(node);
}

/*
* If singly LinkedList contains Cycle then following would be true
* 1) slow and fast will point to same node i.e. they meet
* On the other hand if fast will point to null or next node of
* fast will point to null then LinkedList does not contains cycle.
*/

public boolean isCyclic(){
Node fast = head;
Node slow = head;

while(fast!= null && fast.next != null){
fast = fast.next.next;
slow = slow.next;

//if fast and slow pointers are meeting then LinkedList is cyclic
if(fast == slow ){
return true;
}
}
return false;
}

@Override
public String toString(){
StringBuilder sb = new StringBuilder();
Node current = head.next();
while(current != null){
sb.append(current).append("-->");
current = current.next();
}
sb.delete(sb.length() - 3, sb.length()); // to remove --> from last node
return sb.toString();
}

public static class Node {
private Node next;
private String data;

public Node(String data) {
this.data = data;
}

public String data() { return data; }
public void setData(String data) { this.data = data;}

public Node next() { return next; }
public void setNext(Node next) { this.next = next; }

@Override
public String toString() {
return this.data;
}
}
}





Testing linked list for cycle or loop



In this section we will test linked list using Java main method with two
linked list, one contains cycle and other is not cyclic. You can even write JUnit test cases for
isCyclic() method to
test different linked list with circles and loops at different positions. Here
is first test where linked list does not contain any cycle.

/**
*
* Java program to find if LinkedList contains loop or cycle or not.
* This example uses two pointer approach to detect cycle in linked list.
* Fast pointer moves two node at a time while slow pointer moves one node.
* If linked list contains any cycle or loop then both pointer will meet some time.
*
* @author Javin Paul
*/

public class LinkedListTest {

public static void main(String args[]) {

//creating LinkedList with 5 elements including head
LinkedList linkedList = new LinkedList();
linkedList.appendIntoTail(new LinkedList.Node("101"));
linkedList.appendIntoTail(new LinkedList.Node("201"));
linkedList.appendIntoTail(new LinkedList.Node("301"));
linkedList.appendIntoTail(new LinkedList.Node("401"));

System.out.println("Linked List : " + linkedList);

if(linkedList.isCyclic()){
System.out.println("Linked List is cyclic as it contains cycles or loop");
}else{
System.out.println("LinkedList is not cyclic, no loop or cycle found");
}

}

}

Output:
Linked List : 101-->201-->301-->401
LinkedList is not cyclic, no loop or cycle found





Now let's change the linked list so that it contains cycle or loop,



//creating LinkedList with 5 elements including head
LinkedList linkedList = new LinkedList();
linkedList.appendIntoTail(new LinkedList.Node("101"));
LinkedList.Node cycle = new LinkedList.Node("201");
linkedList.appendIntoTail(cycle);
linkedList.appendIntoTail(new LinkedList.Node("301"));
linkedList.appendIntoTail(new LinkedList.Node("401"));
linkedList.appendIntoTail(cycle);

//don't call toString method in case of cyclic linked list, it will throw OutOfMemoryError
//System.out.println("Linked List : " + linkedList);

if(linkedList.isCyclic()){
System.out.println("Linked List is cyclic as it contains cycles or loop");
}else{
System.out.println("LinkedList is not cyclic, no loop or cycle found");
}

Output:
Linked List is cyclic as it contains cycles or loop





Let me show you an interesting point here, in case you have not noticed already. This is also asked in interviews as,
do you see anything suspicious? toString() method of
LinkedList class is
not checking for cycles or loop and it will throw Exception in thread "main"
java.lang.OutOfMemoryError: Java heap space
,
if you try to print a
linked list with cycles. Now, if you are really lucky then they may ask you to
find start of loop in linked list. That's exercise for you, but let me give you
a hint, look at below diagram of a linked list which contains cycle, red
element is the start of cycle. What is special about it? If you look closely,
you can see that it's the only node in whole linked list which is next node of
other two pointers.


Loop or Cycle detection in Java linked list





































Source:http://javarevisited.blogspot.com/2013/05/find-if-linked-list-contains-loops-cycle-cyclic-circular-check.html

Tidak ada komentar:

Posting Komentar