在循环单链表中查找循环开始的解决方案

时间:2015-05-20 11:29:07

标签: set hashset singly-linked-list

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

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

1 个答案:

答案 0 :(得分:0)

应用下一个算法,将第一个和第二个方法替换为正确的方法,如您的语言

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
    }