【路飞】算法-环形链表

265 阅读2分钟

题目链接 LeetCode: leetcode-cn.com/problems/li… 题目简介 给定一个链表,返回链表开始入环的第一个节点。如果链表无环,这返回null。
如果链表中有某个节点,可以通过跟踪next指针再次到达,则链表中存在环。为了表示给定链表中的环,使用整数pos表示链表尾连接到链表中的位置(索引从0开始)。如果 pos 是 -1,这在该链表中没有环。
不允许修改链表

示例

环形链表1.png

输入: head = [3,2,0,-4], pos = 1
输出: 返回索引为 1 的链表节点
解释: 链表中有一个环,其尾部连接到第二个节点。

环形链表2.png

输入: head = [1,2], pos = 0
输出: 返回索引为 0 的链表节点
解释: 链表中有一个环,其尾部连接到第一个节点。

环形链表3.png

输入: head = [1], pos = -1
输出: 返回 null
解释: 链表中没有环。

解题思路 1、本题使用快慢指针的方式实现
2、慢指针每次向前走一步,快指针每次向前走两步,若快慢指针可以相遇这证明链表有环
3、若链表有环,并且快慢指针相遇时,则此时相遇的位置距离入环点和头节点到入环点的距离是一致的。 4、将一个指针返回头节点,和另一个指针一起每次向前走一步,相遇点则是入环的第一个节点 代码实现

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */

/**
 * @param {ListNode} head
 * @return {ListNode}
 */
 var detectCycle = function(head) {
     if(!head) return null;
     let p = head;  // 慢指针
     let q = head;  // 快指针
     // 先判断一下是否只有一个节点,只有一个节点没环,而且执行会报错,别问我是怎么知道的!!!
     if(!q.next) return null;
     // 循环条件:p和q不相等,并且快指针的next不为null
     // p和q想等则证明有环,当前位置即为相遇点
     do{
         p = p.next;
         q = q.next.next;
     }while(p !== q && q && q.next);
     // 跳出循环的有可能是是next为null,此时则无环
     if(!q || !q.next) return null;
     // 将p重新返回头节点
     p = head;
     // 两个指针都每次向前走一步,相遇时就是入环点
     while( p!== q){
         p = p.next;
         q = q.next;
     }
     // 此时p 和 q想等,返回哪个都可以
     return q;
 }