假设您在Java中有一个链表结构。它由节点组成:

class Node {
    Node next;
    // some user data
}

每个节点都指向下一个节点,除了最后一个节点,它的next为空。假设有一种可能性,列表可以包含一个循环-即最后的节点,而不是有一个空值,有一个引用到列表中它之前的一个节点。

最好的写作方式是什么

boolean hasLoop(Node first)

如果给定的节点是带有循环的列表的第一个,则返回true,否则返回false ?你怎么能写出一个常数的空间和合理的时间呢?

下面是一个带有循环的列表的图片:


当前回答

这是我在java中的解决方案

boolean detectLoop(Node head){
    Node fastRunner = head;
    Node slowRunner = head;
    while(fastRunner != null && slowRunner !=null && fastRunner.next != null){
        fastRunner = fastRunner.next.next;
        slowRunner = slowRunner.next;
        if(fastRunner == slowRunner){
            return true;
        }
    }
    return false;
}

其他回答

检测链表中的循环可以用最简单的方法之一来完成,使用hashmap会导致O(N)复杂度,使用基于排序的方法会导致O(NlogN)复杂度。

当您从head开始遍历列表时,创建一个已排序的地址列表。当您插入一个新地址时,检查该地址是否已经在已排序的列表中,这需要O(logN)复杂度。

我看不出有任何方法可以让这花费固定的时间或空间,两者都会随着列表的大小而增加。

我将使用IdentityHashMap(假设还没有IdentityHashSet)并将每个节点存储到映射中。在存储节点之前,您可以对其调用containsKey。如果节点已经存在,则有一个周期。

ItentityHashMap使用==而不是.equals,这样你就可以检查对象在内存中的位置,而不是它是否具有相同的内容。

func checkLoop(_ head: LinkedList) -> Bool {
    var curr = head
    var prev = head
    
    while curr.next != nil, curr.next!.next != nil {
        curr = (curr.next?.next)!
        prev = prev.next!
        
        if curr === prev {
            return true
        }
    }
    
    return false
}
public boolean isCircular() {

    if (head == null)
        return false;

    Node temp1 = head;
    Node temp2 = head;

    try {
        while (temp2.next != null) {

            temp2 = temp2.next.next.next;
            temp1 = temp1.next;

            if (temp1 == temp2 || temp1 == temp2.next) 
                return true;    

        }
    } catch (NullPointerException ex) {
        return false;

    }

    return false;

}

算法

public static boolean hasCycle (LinkedList<Node> list)
{
    HashSet<Node> visited = new HashSet<Node>();

    for (Node n : list)
    {
        visited.add(n);

        if (visited.contains(n.next))
        {
            return true;
        }
    }

    return false;
}

复杂性

Time ~ O(n)
Space ~ O(n)