LeetCode(力扣) 142题:环形链表 II----快慢指针求解附带详细注释

题目描述

给定一个链表,返回链表开始入环的第一个节点,如果链表无环,则返回None。
为了表示给定链表中的环,我们使用Pos来表示链表尾连接到链表中的位置(索引从0开始)。如果Pos = -1,则在该链表中没有环。注意,Pos仅仅适用于标识环的情况,并不会作为参数传递到函数中。
说明:不允许修改给定的链表

示例

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

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

思路分析

题目要我们找到环形链表入环的节点,相信大家都在学校的操场上跑过圈,将环形链表的环形部分比作操场,操场的入口比作链表入环的节点,假设你和一对小情侣同时从校门口出发去操场跑步,你在跑步 (你一直在跑),把你比作快指针,这对小情侣从校门口出发,一路上走走停停的向操场走去,把他们俩比作慢指针,你们总会有一个时刻在小情侣停下来休息的地方相遇。假如小情侣此时坐下来休息谈恋爱的地方正好在操场门口,你正好也跑到了操场门口,那么恭喜你们相遇了!你们在操场门口相遇了!!你们在链表入环的位置相遇了!!!赶紧返回此时的位置。

在代码设计中,即设置一对快慢指针,初始时快慢指针均位于头节点,同时定义一个集合记录快指针经过的路径,用以判断快指针是否已经绕环形部分一周,慢指针每次前行一个节点,然后快指针围绕环形部分前行一圈,如果环形一圈之后快慢指针没有相遇,说明慢指针现在的位置不在入环的节点,那么慢指针往前走一个节点,快指针继续前行一周,继续判断,直到快慢指针相遇,则他们相遇的位置便是链表入环的位置。逻辑是这样,大家看一下代码设计细节。

代码

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

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        # 当链表中头节点为空或者只有头节点的时候,不满足环形链表形成的条件,返回None
        if head is None:
            return None
        elif head.next is None:
            return None
        # 定义快慢指针,初始位置都指向头节点
        seen = set()
        slow, fast = head, head
        # 以慢指针走到链表终点为循环终止条件
        while slow:
        	# 快指针在当前慢指针位置的前提下绕链表环形一周,如果与慢指针相遇,则返回
        	# 如果没有相遇,那么终止循环,慢指针前行一个节点,继续进入循环判断
            while fast not in seen and fast is not None:
                seen.add(fast)
                fast = fast.next
                if slow == fast:
                    return fast
            seen.clear()
            slow = slow.next        
        return None      

运行结果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Just_do_myself/article/details/118484714
今日推荐