142. 环形链表 II

思路1

遍历链表,第一次访问每个节点都给节点加个标记,当第二次走到环入口,发现有标记,就直接返回

思路2: 参考代码随想录

使用快慢指针,快指针每次走2个节点,慢指针走1个节点
如下图 出x就是求出了环入口
相遇时slow走了:x+y
相遇时fast走了: x+y+n(y+z)
因为fast步长是slow的2倍,所以
2(x+y )= x+y+n(y+z)
x + y = n(y+z)
x = n(y+z) - y
看下边的图,n(y+z)就是fast从相遇点到相遇点绕了n圈,
n(y+z)-y解释一下:绕了n圈 减去y , 其实就是快指针从从相遇点到相遇点绕了n-1圈,最后一圈只走了z那一部分不走y了
既然x的长度等于绕了n圈减去y的长度,那么slow从头节点出发,fast从相遇点出发,每次移动一个节点,走了x个节点后, 就都到达了环入口,也就是他们相遇了,所以可以在代码中判断 如果相遇,相遇点就是环入口

在这里插入图片描述

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def detectCycle2(self, head: Optional[ListNode]) -> Optional[ListNode]:
        # 遍历链表,第一次访问每个节点都给节点加个标记,如果有标记 说明当前节点是环形节点的入口
        cur = head
        while cur:
            try:
                getattr(cur, "flag")
                return cur
            except:
                setattr(cur, "flag", True)
            cur = cur.next
        return None
    
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        # 使用快慢指针,快指针速度是慢指针的2倍
        # 快指针走到相遇点(但还没相遇,慢指针还在前面),剩下需要走k的距离,相遇点到环入口点的距离=k-环入口点到相遇点的距离(相遇点到环入口点的距离 可能包含了多个环)
        # 慢指针从head走到相遇点距离是k,head到环入口点的距离=k-环入口点到相遇点的距离
        # 所以相遇点到环入口点的距离=head到环入口点的距离
        # 所以当两个指针相遇时,slow指针回到head fast指针不变,他们以相同的速度前行,走到环入口点经过的距离是相等的,即相遇时所在位置是环入口点
        fast = slow = head
        while fast and fast.next:
            fast = fast.next.next
            slow = slow.next
            if fast == slow:
                slow = head # 也可以吧fast指向head 都行
                while fast != slow:
                    fast = fast.next
                    slow = slow.next
                return fast
        return None

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值