在循环单链表中查找循环起点的解决方案

Solution to Finding Start of Loop in a Circular Singly Linked List

我发现这个问题的常见解决方案是使用 2 个指针,它们以不同的间隔在链表中前进(即让 p1 一次遍历一个节点,p2 一次遍历两个节点)直到 p1 和p2 相等。示例:Finding loop in a singly linked-list

但是为什么我们不能只使用一个Set来查看是否有重复的节点(前提是我们的节点没有默认的equals和hashCode被覆盖)。

应用下一个算法,将方法 first 和 next 替换为您的语言中的正确方法

slow=llist.first
fast=slow.next
while(true)
{
    if (slow==null || fast == null)
        return false// not circular
    if (fast==slow)
        return true//it is cirular
    fast=fast.next;if (fast!=null)fast=fast.next;
    slow=slow.next;    
}

这里有一个详细的 C# 示例:

    public class Node<T>
    {
        public Node<T> Next { get; set; }
        public T Value { get; set; }
    }
    class LinkedList<T>
    {
        public Node<T> First { get; set; }
        public Node<T> Last { get; set; }
        public void Add(T value)
        {
            Add(new Node<T> { Value = value });
        }
        public void Add(Node<T> node)
        {
            if (First == null)
            {
                First = node;
                Last = node;
            }
            else
            {
                Last.Next = node;
                Last = node;
            }
        }
    }
    static int IndexOfCiruclarity<T>(LinkedList<T> llist)
    {
        var slow = llist.First;
        var fast = slow.Next;
        int index = -1;
        while (true)
        {
            index++;
            if (slow == null || fast == null)
                return -1;
            if (fast == slow)
                return index;
            fast = fast.Next;
            if (fast != null) fast = fast.Next;
            else
                return -1;
            slow = slow.Next;
        }
    }
    void TestCircularity()
    {
        LinkedList<int> r = new LinkedList<int>();
        for (int i = 0; i < 10; i++)
            r.Add(i);
        r.Add(r.First);
        var ci = IndexOfCiruclarity(r);
        //ci = 9
    }