如何在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