1. 程式人生 > >LeetCode Linked List Cycle II

LeetCode Linked List Cycle II

Problem

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Note: Do not modify the linked list.

Follow up: Can you solve it without using extra space?

找到連結串列中環的入口節點,不開闢額外空間

Python 實現


# Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
# # Note: Do not modify the linked list. # # Follow up: # Can you solve it without using extra space? # author li.hzh # Definition for singly-linked list. # class ListNode(object): # def __init__(self, x): # self.val = x # self.next = None class Solution(object): def detectCycle
(self, head): """ :type head: ListNode :rtype: ListNode """ # 假設連結串列中環外節點長度為L, 環內節點長度為C。則有:0 <= L; 0 <= C。例如: # a - > b - > c - > | d -> e ->f -> g - >(d),此時 L= 3, C = 4。 # 現在考慮有環的情況,現有一快一慢兩個指標,慢的每次走一個節點,快的每次兩個,則有,慢節點進入環,需要L步,
# 此時 fast 應該在環內的 L % C = K 的位置。對應上例,就是 3 % 4 = 3 (d + 3 = g)的位置。因此,從環內看, # 相聚還需要 C - K = 4 - 3 = 1步。因此,第一次相遇在d + 1 = e的位置。此時,走到環的初始位,需要 C - (C - K) = K = 3步。 # 那麼問題就變成了,怎麼得到這個K。我們簡單思考,當L < C時,顯然L = K。當 L > C 時,我們想象成兩個每次都一步的指標,一個從頭, # 一個在環內K位行走。當走各走nC步時,環內回到原地。從原點出發的距離環的入口正好還差K步,因此,不論如何,二者必將在入口處相遇。 # 入口位的節點就找到了 if head is None: return None slow = faster = head while faster is not None: slow = slow.next if faster.next is not None: faster = faster.next.next else: return None if slow is faster: break if faster is None: return None slow = head while slow is not faster: slow = slow.next faster = faster.next return slow class ListNode(object): def __init__(self, x): self.val = x self.next = None a = ListNode(1) b = ListNode(2) a.next = b c = ListNode(3) b.next = c d = ListNode(4) c.next = d e = ListNode(5) d.next = e f = ListNode(6) e.next = f g = ListNode(7) f.next = g g.next = d print(Solution().detectCycle(a))

分析

這個題目著實想了很久,水平有限。還是要求不開闢額外空間。整個的思考過程都寫在註釋上了,因為也是一邊計算,一邊思考,一邊作為記錄的。

如果可以使用額外記憶體,那兩道題都很簡單,整個Set存一下級別,判斷Set是否存在即可。

不使用額外記憶體,還是首先考慮追擊,判斷是否相遇,然後通過數學計算相遇節點的位置特點,最終找到入口。詳見註釋的分析過程。