题目

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

To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.

Note: Do not modify the linked list.

Example 1:

  1. Input: head = [3,2,0,-4], pos = 1
  2. Output: tail connects to node index 1
  3. Explanation: There is a cycle in the linked list, where tail connects to the second node.

image.png

Example 2:

  1. Input: head = [1,2], pos = 0
  2. Output: tail connects to node index 0
  3. Explanation: There is a cycle in the linked list, where tail connects to the first node.

image.png

Example 3:

  1. Input: head = [1], pos = -1
  2. Output: no cycle
  3. Explanation: There is no cycle in the linked list.

image.png

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


题意

判断给定链表中是否存在环,存在则返回环的入口结点。

思路

比较简单的就是将所有遍历到的结点记录下来,如果记录了两次则说明当前结点就是所求的结点。

同样可以使用快慢指针的方法:慢指针每次走一步,快指针每次走两步,如果快指针追上慢指针则说明存在环;当判断出存在环后,将快指针重新指向头结点,步进距离改为一个结点,然后使快指针和慢指针同时继续前进,当两者再次相遇时,所处结点就是所求入口结点。证明如下:
image.png
记第一次相遇时慢指针走过的距离为0142. Linked List Cycle II (M) - 图5,快指针走过的距离为0142. Linked List Cycle II (M) - 图6,那么可得如下方程组:
0142. Linked List Cycle II (M) - 图7
化简后可得:
0142. Linked List Cycle II (M) - 图8
说明当快指针重新从A点走到B点时,慢指针从C点出发已经走过了n圈加上z的距离,即也正好落在B点上,因此上述方法能够正确找到环的入口结点。


代码实现

Java

Hash

  1. public class Solution {
  2. public ListNode detectCycle(ListNode head) {
  3. if (head == null) {
  4. return null;
  5. }
  6. Set<ListNode> set = new HashSet<>();
  7. while (head != null) {
  8. if (!set.add(head)) {
  9. return head;
  10. }
  11. head = head.next;
  12. }
  13. return null;
  14. }
  15. }

快慢指针

  1. public class Solution {
  2. public ListNode detectCycle(ListNode head) {
  3. if (head == null) {
  4. return null;
  5. }
  6. ListNode slow = head, fast = head;
  7. while (fast.next != null && fast.next.next != null) {
  8. slow = slow.next;
  9. fast = fast.next.next;
  10. if (slow == fast) {
  11. fast = head;
  12. while (slow != fast) {
  13. slow = slow.next;
  14. fast = fast.next;
  15. }
  16. return slow;
  17. }
  18. }
  19. return null;
  20. }
  21. }

JavaScript

  1. /**
  2. * @param {ListNode} head
  3. * @return {ListNode}
  4. */
  5. var detectCycle = function (head) {
  6. let slow = head
  7. let fast = head
  8. while (fast && fast.next) {
  9. slow = slow.next
  10. fast = fast.next.next
  11. if (slow === fast) {
  12. slow = head
  13. while (slow !== fast) {
  14. slow = slow.next
  15. fast = fast.next
  16. }
  17. return slow
  18. }
  19. }
  20. return null
  21. }