leetcode OJ 判断单链表中是否有环

题目:判断单链表中是否存在环

Binary Tree Preorder Traversal

 


单链表的结构体为:

struct NodeList
{
    int val;
    NodeList *next;
    NodeList(int x) : val(x),next(NULL){}
};

思路很简单,就是搞两个指针,初始值均指向链表头,但是一个跑的快,一个跑的慢。如果链表中没有环,两个指针不会相遇,如果有环的话,则一定会相遇(慢的被套圈了)。

这里我们定下快指针一次走两步,慢指针一次走一步。由于快指针每次追慢指针一格,快慢指针间最大距离<环长(快指针刚过环入口,慢指针进来了),所以在慢指针第一次走完环长之前,快指针必然能追上它(此处为后面做铺垫)。


判断有否存在环的算法,思路有了很简单:

bool hasCircle(NodeList *head)
{
    NodeList *fast=head;
    NodeList *slow=head;
    while(fast!=NULL&&fast->!=NULL)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(fast==slow) return true;
    }
    return true;
}

看了看大牛写的题目扩展,一般还要求找出环入口的位置,

思路是这样的:


假设相遇时慢指针走了s,则快指针走了2s,两者的差s必然为环长的n倍,即s=nl(l为环长),即如果一个指针S1从链表头出发,另一个指针S2从相遇点出发(两者速度相同),S1走到S2出发点时两者一定会相遇(两者都走了nl),而他们的速度是一样的,说明他们在环入口处其实就相遇了,而且是第一次相遇(就在一起了~~~~),这样我们就能定位到环入口了。


有了思路代码也很简单(环已经存在):

NodeList* findCircleEnter(NodeList* head)
{
    NodeList *fast=head;
    NodeList *slow=head;
    while(fast!=NULL&&fast->!=NULL)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(fast==slow) break;
    }
    slow=head;
    while(slow!=head)
    {
        slow=slow->next;
        fast=fast->next;
    }
    return slow;
}


另外,大牛还引申了“如何判断两个无环单链表是否相交”:运用判断单链表环的想法,将其中一个链表首尾相连,然后判断另一个是否有环,若有环则说明两链表相交。


附上链接:

http://www.cppblog.com/humanchao/archive/2012/11/12/47357.html

你可能感兴趣的:(c++,链表,leetcode)