[劍指Offer] 23_連結串列中環的入口節點
阿新 • • 發佈:2019-01-13
題目
如果一個連結串列中包含環,如何找出環的入口節點?
例:
1->2->3->4->5->6
個__________|
思路
- 快慢指標相遇時找到環,並算出環長度,然後用一組間隔環長的雙指標從頭遍歷連結串列,相遇時即為入口。
- 時間複雜度:O(n),最差情況入口在頭節點,遍歷2次連結串列。
- 空間複雜度:O(1)
- 如果連結串列有環,那麼遍歷列表將得到一個周期函式。LN(a + b - a) = LN(a + b + nT - a) T為環的長度,a為環之前的長度,b為環內走過的長度。
此題即求a的值。雙指標遍歷Ps Pf,使Pf2倍快於Ps,那麼總有Pf == Ps,的時候此時Ps = a + b; Pf = 2a + 2b;nT = a + b。因此,當Ps再走a步時,LN(Ps = a + b + a) =LN(a),此時一個從頭出發的節點也正好走到LN(a)。此節點即為入口。- 時間複雜度:O(n),比思路1快,只需要遍歷1次連結串列。
- 空間複雜度: O(1)
程式碼
思路2:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
def entry_node_in_list_loop(head):
"""
:param head: head
:return: entry node
"""
pos = None
slow = fast = head
while slow and fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow is fast:
pos = head
while pos is not slow:
pos = pos.next
slow = slow.next
break
return pos
思考
思路1容易想到,也比較直觀,但是沒有思路2快。思路2需要數學抽象方便理解。
LeetCode上有同樣的題目,可以測試。
142. 環形連結串列 II
題目
給定一個連結串列,返回連結串列開始入環的第一個節點。 如果連結串列無環,則返回 null。
為了表示給定連結串列中的環,我們使用整數 pos 來表示連結串列尾連線到連結串列中的位置(索引從 0 開始)。 如果 pos 是 -1,則在該連結串列中沒有環。
說明:不允許修改給定的連結串列。
示例 1:
輸入:head = [3,2,0,-4], pos = 1
輸出:tail connects to node index 1
解釋:連結串列中有一個環,其尾部連線到第二個節點。
示例 2:
輸入:head = [1,2], pos = 0
輸出:tail connects to node index 0
解釋:連結串列中有一個環,其尾部連線到第一個節點。
示例 3:
輸入:head = [1], pos = -1
輸出:no cycle
解釋:連結串列中沒有環。
進階:
你是否可以不用額外空間解決此題?