題目
給定一個鏈表,返回鏈表開始入環的第一個節點。 如果鏈表無環,則返回 null。
爲了表示給定鏈表中的環,我們使用整數 pos 來表示鏈表尾連接到鏈表中的位置(索引從 0 開始)。 如果 pos 是 -1,則在該鏈表中沒有環。
說明:不允許修改給定的鏈表。
示例 1:
輸入:head = [3,2,0,-4], pos = 1
輸出:tail connects to node index 1
解釋:鏈表中有一個環,其尾部連接到第二個節點。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/linked-list-cycle-ii
分析
三種解法
- 給ListNode添加count基數,訪問到就+1,如果遇到計數爲2表明被訪問了兩次,就是環的開始。
- 雙指針法,快慢指針,快指針走兩步,慢指針走一步,如果有環就會相遇。找到有環之後,新一個指針從頭開始,慢指針繼續向前,畫個圖應該比較明顯的能夠看出,兩人會再同一個點相遇。
- 藉助輔助空間O(N),採用一個hashmap,訪問過的加入到hashmap裏,遇到hashmap中已經有的,就表明遇到環了,
解法
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func detectCycle(head *ListNode) *ListNode {
if head == nil || head.Next == nil {
return nil
}
slow, fast := head, head.Next
for slow != fast {
if fast == nil || fast.Next == nil {
return nil
}
slow = slow.Next
fast = fast.Next.Next
}
// fmt.Printf("有環\n")
// 探測到有環了,放慢腳步
// aNew 站在0位置了,而slow則站在了-1位置
slow = slow.Next
for aNew := head; aNew != slow; aNew, slow = aNew.Next, slow.Next {
// fmt.Printf("1: %v, 2: %v\n", aNew.Val, slow.Val)
}
return slow
}
- 解法2
unc detectCycle(head *ListNode) *ListNode {
var mm = make(map[*ListNode]bool)
cur := head
for cur != nil {
if _, ok := mm[cur]; ok {
return cur
}
mm[cur] = true
cur = cur.Next
}
return nil
}