如何检测LinkedList中的无限循环

这是一个非常常见的面试问题。系统会询问您是否有一个链接列表,只能在一个方向上遍历,如果该链接列表中有一个循环,您将如何检测它?

对于这个具体问题,最佳答案采访者正在寻找的是“ Floyd's Cycle-Finding Algorithm”。该算法提出了一种解决方案,其中只有一个指针遍历列表,建议您一次有两个指针。两个指针都将从链表的第一个节点开始,并使用下一个属性进行遍历。

不同之处在于它们在每一步中跳跃的节点数量。第一个节点每次跳转到下一个节点,而另一个节点一次跳转两个节点。第一个节点称为较慢的节点乌龟,第二个较快的节点称为兔子

Tortoise_and_hare_algorithm

乌龟和野兔算法

此遍历确保如果链接链接中存在循环,则两个节点都将确实在其遍历路径中的某个位置相遇。它具有O(n)复杂性。

让我们使用java示例代码验证这一点。

我编写了一个尽可能少的单链表代码,仅用于演示此示例。

<span style="color:#000000">package com.howtodoinjava.demo.core;

public class SinglyLinkedList {

	private Node start;

	public void add(Integer i)
	{
		Node node = new Node(i);
		if(start == null)
			start = node;
		else
		{
			Node temp = start;
			while(temp.next != null)
			{
				temp = temp.next;
			}
			temp.next = node;
		}
	}

	public Node getStart()
	{
		return start;
	}

	static class Node
	{
		Node(Integer i)
		{
			this.value = i;
		}

		private Integer value;
		private Node next;
		public Integer getValue() {
			return value;
		}
		public void setValue(Integer value) {
			this.value = value;
		}
		public Node getNext() {
			return next;
		}
		public void setNext(Node next) {
			this.next = next;
		}
	}
}
</span>

现在,让我们首先测试上面的链表而不是循环,然后在其中使用循环。

<span style="color:#000000">package com.howtodoinjava.demo.core;

public class FindLoopsInLinkedList
{
	public static void main(String args[]) {

		FindLoopsInLinkedList finder = new FindLoopsInLinkedList();

		SinglyLinkedList sampleList = new SinglyLinkedList();
		// First Insert randomly ten elements in a linked list
		for (int i = 0; i < 10; i++) {
			sampleList.add(i);
		}

		System.out.println("Loop Existence : " + finder.doesLoopExist(sampleList));
		System.out.println("Loop Existence : " + finder.doesLoopExist(finder.createLoop(sampleList)));
	}

	public boolean doesLoopExist(SinglyLinkedList listToCheck) {
		SinglyLinkedList.Node tortoise = listToCheck.getStart();
		SinglyLinkedList.Node hare = listToCheck.getStart();

		try {
			while (true) {
				tortoise = tortoise.getNext();
				hare = hare.getNext().getNext();
				if (tortoise == hare) {
					return true;
				}
			}
		} catch (NullPointerException ne) {
			return false;
		}
	}

	private SinglyLinkedList createLoop(SinglyLinkedList sampleList) {
		sampleList.getStart().getNext().getNext().getNext().setNext(sampleList.getStart().getNext());
		return sampleList;
	}
}
</span>

在上面的程序中,我们创建了一个链表,我们在这个列表中插入了10个元素。不,当我们在行号中检查循环存在时。15它是虚假的。

但是,当在第167行中,我们在链表中创建了一个循环,结果为真。

以上程序的输出是这样的:

循环存在:false [第15行]
循环存在:true [第16行]

如你所见,一旦我们在第一行插入循环。16,我们的算法实现能够检测到它。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值