142. 环形链表 II + 快慢指针 + Set

142. 环形链表 II

LeetCode_142

题目描述

题解分析

  1. 判断链表是否存在环
  • 对于这个问题我们可以采用“快慢指针”的方法。就是有两个指针fast和slow,开始的时候两个指针都指向链表头head,然后在每一步操作中slow向前走一步即:slow = slow->next,而fast每一步向前两步即:fast = fast->next->next。由于fast要比slow移动的快,如果有环,fast一定会先进入环,而slow后进入环。当两个指针都进入环之后,经过一定步的操作之后二者一定能够在环上相遇,并且此时slow还没有绕环一圈,也就是说一定是在slow走完第一圈之前相遇。
  1. 寻找链表中环的起点

    • 从链表起点head开始到入口点的距离a,与从slow和fast的相遇点(如图)到入口点的距离相等。
    • 我们就可以分别用一个指针(ptr1, prt2),同时从head与slow和fast的相遇点出发,每一次操作走一步,直到ptr1 == ptr2,此时的位置也就是入口点!
  2. 计算链表中环的结点个数

    • 从相遇点开始slow和fast继续按照原来的方式向前走slow = slow -> next; fast = fast -> next -> next;直到二者再次相遇,此时经过的步数就是环上节点的个数 。

代码详情

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow = head, fast = head;
        while(fast != null){
            if(fast.next == null)
                return null;
            slow = slow.next;
            fast = fast.next.next;
            //slow还没有走完一圈快慢指针必定会相遇
            if(fast == slow){
                ListNode now = head;
                //从相遇的地方再次循环
                while(now != slow){
                    slow = slow.next;
                    now = now.next;
                }
                return now;
            }
        }
        return null;
    }
}
posted @ 2021-03-04 21:57  Garrett_Wale  阅读(73)  评论(0编辑  收藏  举报