【思维】快慢指针——LEETCODE环形链表 II

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

经典快慢指针,首先用快慢指针s,f从head开始扫描,设两个指针在一段时间t后相遇

此时慢指针走了t步,设t=a+b,其中a是环外的,b是环内部分

此时快指针走了2t步,同时快指针一定在环上绕了k圈,设环长度为c,有等式2t=(a+kc+b)=2(a+b)

  所以a+b=kc=t

我们此时需要一个重要的结论:所有走到起始点的步数都可以表示为a+kc(显然,把环外的走了,然后走k圈环内的)

然后只要让s再往前走a步就行,为了实现这个,我们再用一个慢指针,从head出发,直到和s相遇,就是环入口

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(head==NULL)return NULL;
        ListNode *s=head;//慢指针
        ListNode *f=head;//快指针
        int t=0;
        while(1){//碰到NULL说明没有环
            ++t;
            //cout<<t<<" ";
            if(s->next!=NULL)
                s=s->next;
            else return NULL;
            if(f->next!=NULL)
                f=f->next;
            else return NULL;
            if(f->next!=NULL)
                f=f->next;
            else return NULL;

            if(s==f){//快慢指针相遇
                auto res=head;
                while(res!=s){
                    s=s->next;
                    res=res->next;
                }
                return res;
            }
        }
        return NULL;
    }
};

 

posted on 2020-06-16 23:53  zsben  阅读(239)  评论(0编辑  收藏  举报

导航