1. 题目描述:
  2. 给定一个链表,判断链表中是否有环。
  3. 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
  4. 如果链表中存在环,则返回 true 否则,返回 false
  5. var hasCycle = function (head) {
  6. //TODO
  7. };

我的回答

  1. var hasCycle = function (head) {
  2. //TODO
  3. let current = head
  4. let list = []
  5. while(head.next) {
  6. for(let i = 0; i < list.length; i++) {
  7. let item = list[i]
  8. if (item == head.next) {
  9. return i
  10. }
  11. }
  12. head = head.next
  13. list.push(head)
  14. }
  15. return -1
  16. };

参考回答

https://leetcode-cn.com/problems/linked-list-cycle/solution/

  1. // 思路:快慢指针,快的速度是慢的两倍。
  2. // 第一次相遇则是有环,且相遇点距环入口距离加上入环前长度会是环的整数倍。
  3. // 然后从相遇点以及头部同时进行两个指针,相遇时就是环入口
  4. // 关键点:注意边界条件,比如第一次确定有环的遍历时要注意开始条件是fast===slow,不能直接while(fast!==slow)这样;
  5. // 一次移动两次的指针,fast=fast.next.next,条件里应当是fast.next非空进行(非空的fast.next有next),同时也要加上fast非空的条件,避免出现报错(fast为空的时候)
  6. var detectCycle = function (head) {
  7. let fast = head, slow = head
  8. if (!fast || !fast.next) return null
  9. do {
  10. fast = fast.next.next
  11. slow = slow.next
  12. } while (fast && fast.next && fast !== slow)
  13. if (fast !== slow) return null
  14. fast = head
  15. while (fast !== slow) {
  16. fast = fast.next
  17. slow = slow.next
  18. }
  19. return slow
  20. };

LeetCode题解

假想「乌龟」和「兔子」在链表上移动,「兔子」跑得快,「乌龟」跑得慢。当「乌龟」和「兔子」从链表上的同一个节点开始移动时,如果该链表中没有环,那么「兔子」将一直处于「乌龟」的前方;如果该链表中有环,那么「兔子」会先于「乌龟」进入环,并且一直在环内移动。等到「乌龟」进入环时,由于「兔子」的速度快,它一定会在某个时刻与乌龟相遇,即套了「乌龟」若干圈。

我们可以根据上述思路来解决本题。具体地,我们定义两个指针,一快一满。慢指针每次只移动一步,而快指针每次移动两步。初始时,慢指针在位置 head,而快指针在位置 head.next。这样一来,如果在移动的过程中,快指针反过来追上慢指针,就说明该链表为环形链表。否则快指针将到达链表尾部,该链表不为环形链表。

image.png
image.png
为什么我们要规定初始时慢指针在位置 head,快指针在位置 head.next,而不是两个指针都在位置 head(即与「乌龟」和「兔子」中的叙述相同)?

观察下面的代码,我们使用的是 while 循环,循环条件先于循环体。由于循环条件一定是判断快慢指针是否重合,如果我们将两个指针初始都置于 head,那么 while 循环就不会执行。因此,我们可以假想一个在 head 之前的虚拟节点,慢指针从虚拟节点移动一步到达 head,快指针从虚拟节点移动两步到达 head.next,这样我们就可以使用 while 循环了。

当然,我们也可以使用 do-while 循环。此时,我们就可以把快慢指针的初始值都置为 head。

  1. func hasCycle(head *ListNode) bool {
  2. if head == nil || head.Next == nil {
  3. return false
  4. }
  5. slow, fast := head, head.Next
  6. for fast != slow {
  7. if fast == nil || fast.Next == nil {
  8. return false
  9. }
  10. slow = slow.Next
  11. fast = fast.Next.Next
  12. }
  13. return true
  14. }