在java中使用HashMap在链表中查找循环

时间:2017-07-07 13:05:17

标签: java linked-list hashmap

我正在使用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;
}

3 个答案:

答案 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;
}

并遵循Java Code Conventions

答案 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;
}