题目描述
リンク リストを指定すると、リンク リストがループに入り始める最初のノードを返します。リンク リストにループがない場合は 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
解释:链表中没有环。
思路分析
タイトルでは、リンクリストがリングに入るノードを見つけるように求められています。誰もが学校の校庭で走り回ったことがあると思います。リンクリストのリング部分を校庭に、校庭の入り口とそのノードを比較してください。リンクされたリストがリングに入ります。あなたと 2 組の小さなカップルが校門からスタートして、同時に校庭を走り始めたとします。あなたは走っています (走り続けています)、そしてあなたは速いポインタのようなものです。二人はスローポインターに例えられ、若いカップルが休憩する場所で出会う瞬間が必ずあります。若いカップルが座って休息し、恋に落ちる場所がたまたま遊び場の門で、あなたが偶然遊び場の門に走ったとしたら、あなたに会えたことをおめでとうございます。遊び場の門で会ったんですね!!リンクリストがリングに入る位置で出会った!!!急いで今いる場所に戻ってください。
コード設計では、高速ポインタと低速ポインタのペアが設定されます。最初は、高速ポインタと低速ポインタがヘッド ノードに配置されます。同時に、高速ポインタが通過したかどうかを判断するために、高速ポインタが通過したパスを記録するコレクションが定義されます。高速ポインタはリング部分を一周しました 低速ポインタはそのたびに前進します ノードがあり、その後高速ポインタがリング部分を周回して前進します リング一周後に高速ポインタと低速ポインタが交わらない場合は、スローポインタの現在位置がリングに入ったノードではない その後、スローポインタは1ノード分前進し、高速ポインタは前進を続けます 1週間、高速ポインタとスローポインタが出会うまで判定を続け、その後位置が決定されますそれらが交わる場所が、リンクされたリストがリングに入る位置です。ロジックはこんな感じです。コード設計の詳細を見てみましょう。
代码
# 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
运行结果