如何在Java中的链接列表中检测循环与示例
时间:2020-02-23 14:34:50 来源:igfitidea点击:
"如何在LinkedList中检测循环/周期"。
这个问题与数据结构更有关。
如果存在循环,我们还可以找到循环的启动节点。
你可能思考的第一个方法可能是:
- 通过每个节点遍历到结束,使用访问的标志跟踪访问的节点。
- 如果找到已访问的节点,则链接列表中有一个循环,如果遍历到结束,则链接列表中没有循环
但上述方法的问题是,在大多数情况下,我们无法更改LinkedList节点的数据结构,因此我们将无法将访问的标志添加到其中。
有效的方法:
对于这个问题的有效方法将是Floyd的循环检测算法,因此本体的步骤将是:
- 使用两个指针fastptr和stropptr并初始化链接列表头部
- 每次迭代中的一个节点将FastPtr移动到两个节点和慢动网。
- 如果fastptr和stropptr在某些迭代时会满足,则LinkedList中存在一个循环。
- 如果FastPtr到达LinkedList的末尾而不会见慢指针,则LinkedList中没有循环(即FastPtr-> Next或者FastPtr-> Next-> Next成为Null)
这个Algo的Java代码将是
public boolean ifLoopExists() {
Node fastPtr = head;
Node slowPtr = head;
while (fastPtr != null && fastPtr.next != null) {
fastPtr = fastPtr.next.next;
slowPtr = slowPtr.next;
if (slowPtr == fastPtr)
return true;
}
return false;
}
以上解决方案适用于O(n)时间复杂度和O(1)空间复杂性。
允许在没有循环的情况下创建链接列表:
允许创建一个名为"linkedlist.java"的Java程序
package org.igi.theitroad;
public class LinkedList{
private Node head;
private static class Node {
private int value;
private Node next;
Node(int value) {
this.value = value;
}
}
public void addToTheLast(Node node) {
if (head == null) {
head = node;
} else {
Node temp = head;
while (temp.next != null)
temp = temp.next;
temp.next = node;
}
}
public void printList() {
Node temp = head;
while (temp != null) {
System.out.format("%d ", temp.value);
temp = temp.next;
}
System.out.println();
}
public boolean ifLoopExists() {
Node fastPtr = head;
Node slowPtr = head;
while (fastPtr != null && fastPtr.next != null) {
fastPtr = fastPtr.next.next;
slowPtr = slowPtr.next;
if (slowPtr == fastPtr)
return true;
}
return false;
}
public static void main(String[] args) {
LinkedList list = new LinkedList();
//Creating a linked list
list.addToTheLast(new Node(5));
list.addToTheLast(new Node(6));
list.addToTheLast(new Node(7));
list.addToTheLast(new Node(1));
list.addToTheLast(new Node(2));
list.printList();
//Test if loop existed or not
System.out.println("Loop existed-->" + list.ifLoopExists());
}
}
逻辑上,我们的链接列表可以表示为:
运行上面的程序,我们将获取以下输出:
5 6 7 1 2 Loop existed-->false
允许在LinkedList中创建一个循环
现在我们将上次节点连接到NodeWith值7,它将在链接列表中创建循环,因此更改高于Main方法:
public static void main(String[] args) {
LinkedList list = new LinkedList();
//Creating a linked list
Node loopNode=new Node(7);
list.addToTheLast(new Node(5));
list.addToTheLast(new Node(6));
list.addToTheLast(loopNode);
list.addToTheLast(new Node(1));
list.addToTheLast(new Node(2));
list.printList();
//creating a loop
list.addToTheLast(loopNode);
//Test if loop existed or not
System.out.println("Loop existed-->" + list.ifLoopExists());
}
逻辑上我们的LinkedList循环可以表示为:
运行上面的程序,我们将获取以下输出:
5 6 7 1 2 Loop existed-->true

