142.环形链表II

142.环形链表II
代码随想录解析
题目:
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。

解析:
:通过两指针fast和slow,fast一次走两个单位,slow一次走一个单位看两者是否相遇,若相遇则有环,若不相遇则无环。
①:若无环返回 NULL。
②:若有环
:若有环通过两指针index1,index2。index1指向head,index2指向fast,index1和index2同时以1的速度移动,相遇即为入环第一个节点处。不过我没有用index1,index2而是直接将slow指向head移动slow,fast直到相遇。

1: slow指针走过的节点数为: x + y, fast指针走过的节点数:x + y + n (y + z)
解释:
slow而言:相对fast而言静止,在没走完一圈时就会被赶上(fast走一圈slow才走半圈,在思考fast最后一下跳过slow时,若最后一下跳过,则前一个位置slow,fast重合,若最后一下没有跳过slow,你怎么自然就是重合(抽象理解:fast相对slow一次移动一个位置更不可能跳过))。只会走y距离不会走y加上n圈的距离。
fast而言:当两者都进入圈内,相对而言slow不动,fast以速度为1来追赶slow,所以必然相遇,同时只耗费一段距离或者刚好相遇。
如果x很长,y+z很短fast会先跑N圈,当slow进入圈内,再实现追赶,在圈内只耗费一段距离或者刚好相遇(通过将两者相对来思考)。

fast指针至少要多走一圈才能相遇slow指针。
2: 因为fast指针是一步走两个节点,slow指针一步走一个节点, 所以 fast指针走过的节点数 = slow指针走过的节点数 * 2:公式:(x + y) * 2 = x + y + n (y + z)

整理公式之后为如下公式:x = (n - 1) (y + z) + z

n分为两种情况(n始终大于0):
:当 n等于1,从相遇点设置一个指针,从head节点处设置一个指针,统一移动每次移动一个单位,当两者相遇即入环第一个节点(当起始点移动 x 的长度到达入环第一个节点处,相遇点指针移动了 z 的长度到达入环第一个节点处,此时两者相遇相遇)。
:当 n 大于1,y+z为一圈的长度,同理:从相遇点设置一个指针,从head节点处设置一个指针,统一移动每次移动一个单位,当两者相遇即入环第一个节点(当起始点移动 x 的长度到达入环第一个节点处,相遇点指针移动了 z 的长度加上(n-1)圈的长度入环第一个节点处,此时两者相遇)。

总结就是:两个指针每次走一个单位,然后相遇,相遇点即入环第一个节点。

关键在于公式的分析:x = (n - 1) (y + z) + z
使用指针的移动模拟长度,重点在于移动后两者能刚好在入环第一个节点处相遇。

代码:

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *fast = head;
        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 slow;
            }
        }
        return NULL;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值