首先,我应该提一下,我已经检查并理解了最流行的算法,用于检测链接列表是否有循环(讨论此How to detect a loop in a linked list?)
然而,我尝试实现自己的想法,它似乎适用于我的示例 - 但它在http://leetcode.com/的执行时间失败,这使我认为它可以进入无限循环。
我的问题是:我需要知道我的代码是否正确,或者在某些情况下它确实会进入无限循环。
这是单链表的定义。
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
这是功能:
public boolean hasCycle(ListNode head) {
//create a list that will contain the elements that have been visited
List<ListNode> ref = new ArrayList<ListNode>();
ListNode element = head;
//add the first element to the list
ref.add(head);
boolean contains = false;
//the special case when the linkedlist is empty
if(head==null)
return false;
while(contains == false){
if(element.next!=null && !ref.contains(element.next)){
ref.add(element.next);
element = element.next;
contains = false;
}
else if (ref.contains(element.next))
contains = true;
else if(element.next == null)
return false;
}
return contains;
}
答案 0 :(得分:0)
我认为您的代码无法进入无限循环。遵循算法的可能控制流程:
在任何时候都没有一个分支导致程序状态没有以某种方式前进,因此可以安全地说无限循环不是问题。
您的算法的真正问题似乎是它的时间复杂性。确保java.util.ArrayList不包含特定值需要完全遍历列表并每次在每个元素上调用Object#equals。如果你没有使用像你所链接的更传统的循环节点链接检查算法之一,我肯定建议使用java.util.HashSet代替这样的东西。它通过设计提供非常快速的查找,以确定元素是否存在于其中。
此外,如果您处于一种不太习惯的情况下,其中存在为节点编写的自定义equals和hashCode方法,则可能不得不求助于通过使用hashCode和equals方法通过系统代理的包装类来跟踪节点。 #identityHashCode对真实节点的调用和引用相等性检查。否则,当一个人确实没有循环时,算法可能会确定存在一个循环。