Leetcode面试题 02.08. 环路检测

Every day a leetcode

题目来源:面试题 02.08. 环路检测

解法1:快慢指针

设置快慢两个指针分别为fast和slow,初始化都指向head。

slow每次走一步,fast每次走两步。

由于fast走得更快,如果有环,fast一定先进入环,slow后进入环。当两个指针都进入环后,两个指针一定能在环上相遇,这样就能判断是否有环。

如下图所示,当slow刚进入环时,fast早已进入环。因为fast每次比slow多走一步,且fast和slow的距离小于环的长度,所以fast和slow相遇时,slow所走的距离不超过环的长度。Leetcode面试题 02.08. 环路检测_第1张图片
如下图所示,设头结点到环的入口点的距离为a,环的入口点沿环的方向到相遇点的距离为x,环长为r,相遇时fast绕了n圈。

Leetcode面试题 02.08. 环路检测_第2张图片
则有:2 * (a+x)=a+n * r+x,即:a=n*r-x。
显然从头结点到环的入口点的距离等于n倍的环长减去环的入口点到相遇点的距离。

因此可以设置两个指针,一个指向head,一个指向相遇点,两个指针同步移动(一次走一步),相遇点即为环的入口点。

代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) {
    if(head == NULL || head->next == NULL) return NULL;
    struct ListNode* slow=head;
    struct ListNode* fast=head;
    while(fast && fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow == fast) break;
    }
    //没有环,返回NULL
    if(fast!=slow) return NULL;
    struct ListNode* p1=head;
    struct ListNode* p2=slow;
    while(p1!=p2)
    {
        p1=p1->next;
        p2=p2->next;
    }
    return p1;
}

结果:
Leetcode面试题 02.08. 环路检测_第3张图片

解法2:hash

详情见官方题解环路检测:方法一:哈希表

你可能感兴趣的:(Every,day,a,leetcode,leetcode,链表,算法)