我正在使用hashmap编写链表中的lop检测代码。为什么它会进入无限循环?
boolean hasCycle(Node head) {
HashMap<Integer,Node> map = new HashMap<Integer,Node>();
//<Address,data>
if(head == null || head.next == null)
return false;
Node p = head;
while(p.next!=null)
{
if(map.containsValue(p.next))
{
return true;
}
else
{
map.put(p.data,p.next);
}
p = p.next;
}
return false;
}
答案 0 :(得分:2)
您的代码调用
map.containsValue(p.next)
此方法遍历整个地图,查找与传递的参数相等的对象。为此,它会调用您的Node.equals()
方法。很可能这是它进入无限循环的地方。
要解决此问题,您可以使用Node对象的HashSet(如评论中所述)并检查您的equals()
和hashCode()
方法是否正确。但是还有另一种检查周期的方法,它不涉及使用任何额外的内存。你只需要使用两个迭代器,一个以另一个的速度的一半。如果有一个循环,那么速度越快的迭代器就会越慢。
答案 1 :(得分:2)
使用Node作为键,使用数据字段作为值,然后检查HashMap是否包含密钥:
boolean hasCycle(Node head) {
HashMap<Node,Integer> map = new HashMap<Node,Integer>();
if(head == null || head.next == null)
return false;
Node p = head;
while(p.next!=null) {
if (map.containsKey(p.next)) {
return true;
} else {
map.put(p.next,p.data);
}
p = p.next;
}
return false;
}
答案 2 :(得分:0)
您是否在.equals()
课程中定义了.hashCode()
和Node
?如果没有,则默认为==
,如果HashMap
在您插入节点或在内存中移动节点时复制节点,那么您的等效性将失败,因为==
比较内存地址。
假设您的节点类类似于
public class Node{
public int data;
public Node next;
}
你可以将它们定义为
@Override
public int hashCode(){
int nextData=next.data;
return data^nextData;
}
@Override
public boolean equals(Object other){
boolean equal=false;
if(other!=null&&other instanceof Node){
Node otherNode=(Node)other;
if(otherNode.data==data){
if(otherNode.next==null&&next==null){
equal=true;
}else if(otherNode.next!=null&&next!=null){
if(otherNode.next.data==next.data){
equal=true;
}
}
}
}
return equal;
}