【问题标题】:finding loop in linked list using HashMap in java在java中使用HashMap在链表中查找循环
【发布时间】:2017-07-07 13:05:16
【问题描述】:

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

【问题讨论】:

  • 你为什么用HashMap而不是HashSet
  • 能否提供测试数据
  • ericlippert.com/2014/03/05/how-to-debug-small-programs -- 向鸭子解释为什么它应该无限循环。如果这没有帮助,请使用调试器并单步执行。当它做了你没想到的事情时,你就发现了问题。
  • 对于简单的情况,它看起来没有错。测试数据会很好。
  • @parimal 如果您希望我们能够为您提供帮助,您必须提供Minimal, Complete, and Verifiable example,否则您的问题将被关闭为“无法再复制的问题”。

标签: java linked-list hashmap


【解决方案1】:

以Node为key,以data字段为value,然后检查HashMap是否包含key:

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

【讨论】:

  • 或者使用HashSet,不要在意值。
  • 当然,但是正如 OP 已经说过的那样,他们想使用 HashMap 来实现它,因为它已经与 HashSet 一起使用。
  • 啊,那条评论是新的。那么,据推测,OP 想要将HashMap&lt;Value,Node&gt; 用于其他目的(也许使算法检查循环并在同一通道中执行其他工作),这意味着HashMap&lt;Node, Value&gt; 也没有用。我怀疑它还是被误导了......
【解决方案2】:

你的代码调用

map.containsValue(p.next)

此方法遍历整个地图,寻找与传递的参数等于的对象。为此,它会调用您的 Node.equals() 方法。这很可能是它进入无限循环的地方。

要解决它,您可以使用 Node 对象的 HashSet(如 cmets 中所述)并检查您的 equals()hashCode() 方法是否正确。但是还有另一种检查周期的方法,它不涉及使用任何额外的内存。您只需使用两个迭代器,一个以另一个速度的一半运行。如果有循环,则越快的迭代器会越慢。

【讨论】:

    【解决方案3】:

    您是否在 Node 类中定义了 .equals().hashCode()?如果不是,则默认为==,如果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;
    }
    

    【讨论】:

    • Java 的 HashMap 不会克隆它包含的任何对象;当它展开时,它只是将 references 复制到相同的对象。因此,如果 OP 未定义 hashCode()equal(),则 hasCycle() 方法将起作用。我认为它们的定义是错误的。
    猜你喜欢
    • 2021-10-16
    • 2012-05-03
    • 2018-12-27
    • 2020-10-15
    • 1970-01-01
    • 2011-02-25
    • 1970-01-01
    相关资源
    最近更新 更多