Leetcode 142. 环形链表 II(详解)

142. 环形链表 II(点击查看原题)

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

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。

说明:

不允许修改给定的链表。

进阶:

你是否可以使用 O(1) 空间解决此题?

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

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

解题思路

这位大佬分析的很清楚,我也就直接摘抄过来作为这道题目的分析了,。
以下分析截取自:双指针技巧汇总

第一次相遇时,假设慢指针 slow 走了 k 步,那么快指针 fast 一定走了 2k 步,也就是说比 slow 多走了 k 步(也就是环的长度)。

在这里插入图片描述

设相遇点距环的起点的距离为 m,那么环的起点距头结点 head 的距离为 k - m,也就是说如果从 head 前进 k - m 步就能到达环起点。巧的是,如果从相遇点继续前进 k - m 步,也恰好到达环起点。

在这里插入图片描述

所以,只要我们把快慢指针中的任一个重新指向 head,然后两个指针同速前进,k - m 步后就会相遇,相遇之处就是环的起点了。

实现代码

struct ListNode *detectCycle(struct ListNode *head) 
{
    struct ListNode *fast,*slow;
    fast = slow = head;
    bool hasCycle =false;    
    while(fast!=NULL && fast->next!=NULL)  //因fast每次走两步,若不判断fast->next是否为空,可能会出现当fast->next->next为空时,fast->next已经为空了的情况
    {
        fast = fast->next->next;    //快指针每次走两步
        slow = slow->next;    //慢指针每次走一步
        if(fast==slow)     
        {
            hasCycle = true;   
            break;
        }
    }
    if(hasCycle==false)   //若==false,说明fast遇到了NULL,也就是链表没环
    {
        return NULL;
    }

    fast = head;     //排除了链表没环的情况,就说明有环,把快指针指向head,重新向后走
    while(fast!=slow)    
    {
        fast = fast->next;   //这次fast指针从head节点出发每次走一步
        slow = slow->next;   //slow指针从上次位置继续向后走,每次走一步
    }
    return slow;   //当循环结束后说明fast与slow又相遇了,返回slow
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值