快慢指针

给定一个有环链表,实现一个算法返回环路的开头节点。

有环链表的定义:在链表中某个节点的next元素指向在它前面出现过的节点,则表明该链表存在环路。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:tail connects to node index 1
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0
输出:tail connects to node index 0
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入:head = [1], pos = -1
输出:no cycle
解释:链表中没有环。

在这里插入图片描述
如图,这就是一个有环的链表,可以看3-10是的,这个问题可以想像成一个数学问题。
如果有两个人同时同地出发跑步,一个快一个慢,那么只有在操场是圆的时,快的才能与慢的相遇。

如果操场是这个链表的形状,那怎么才能知道他们入环的地点呢?
设:
fast的速度是2v
slow的速度是v
在这里插入图片描述
那当他们第一次相遇(S1后面那个红点处)时:
fast走了:L+S1+S2+S1
slow走了:L+S1

时间是相同的所以

2*(L+S1) = L+S1+S2 +S1

L=S2
那我们让快fast的从S1继续跑,让慢slow的从起点跑,当快fast跑完S2,慢slow也跑完了L,相遇时即是环的入口。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) 
{
    struct ListNode *fast = head;
    struct ListNode *slow = head;
    while(fast != NULL && fast->next != NULL)//可以把这个判断条件最后写,看看循环体内有哪些左值
    {
        fast = fast->next->next;//快的一次走两个
        slow = slow->next;//慢的一次走一个
        if (fast == slow)//追上了,肯定就是环了
        {
            slow = head;//慢的从头,快的不变
            while (fast != slow)//直到相遇
            {
                fast = fast->next;
                slow = slow->next;
            }
            return fast;
        }
    }
    return NULL;
    /*
    空链表
    只有一个结点
    */
}
©️2020 CSDN 皮肤主题: 1024 设计师: 上身试试 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值