一、题目描述
二、解题思路
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
* 思考,就可以直接使用哈希表进行解决
* 执行用时:88 ms, 在所有 JavaScript 提交中击败了92.47%的用户
* 内存消耗:41 MB, 在所有 JavaScript 提交中击败了8.17%的用户
*/
// var detectCycle = function(head) {
// let map = new Map();
// while (head) {
// if (map.has(head)) {
// return map.get(head);
// }
// map.set(head, head);
// head = head.next;
// }
// return head;
// };
/**
* 方案二,采用双指针的形式,
* 思路一样,如果之前节点找到了这个节点,就直接返回
* 目前这个版本,超出时间限制,
* 如果是尾链表形成环的话,那么其实快指针比慢指针多走一步。快指针第一次重复的点就是入环点,对于哈希表是这样的。
* 如果是双指针呢。快指针先到到入环点,经过,慢指针后到入环点。每次都是都走一步,所以这个版本永远不会相逢,所以会超出时间限制。
*/
// 这个版本可以判断是否可以追上,并且得到追上的节点,但是这个节点不是入环的节点。
// var detectCycle = function (head) {
// if (!head || head.next === null) return null;
// let slow = head;
// let fast = head.next;
// while (fast && fast.next) {
// if (fast === slow) {
// return slow;
// }
// slow = slow.next;
// fast = fast.next.next;
// }
// return null;
// }
/**
* 参考:https://leetcode-cn.com/problems/linked-list-cycle-ii/solution/huan-xing-lian-biao-ii-by-leetcode-solution/ 题解
* 继续深入,如何寻找到入环的节点。两个节点同时从起点开始走
* 1. 快针走的是慢针的两倍。
* 2. 因为慢针走过的路,快针已经走过一遍;
* 3. 快针走过的剩余路程,也就是和慢针走过的全部路程相等。(a+b = c+b)
* 4. 刨去快针追赶慢针的半圈(b),剩余路程即为所求入环距离(a=c)
* 所以当他们相遇的时候,这时候,这时候声明一个新的指针从 head 开始走,当它和慢指针相遇的时候,就是他们相遇的节点。
执行用时:96 ms, 在所有 JavaScript 提交中击败了66.71%的用户
内存消耗:40.1 MB, 在所有 JavaScript 提交中击败了90.07%的用户
*/
var detectCycle = function (head) {
if (head === null) return null;
let slow = head;
let fast = head;
while (fast !== null) {
slow = slow.next;
if (fast.next !== null) {
fast = fast.next.next;
} else {
return null;
}
if (fast === slow) {
let ptr = head;
while (ptr !== slow) {
ptr = ptr.next;
slow = slow.next;
}
return ptr;
}
}
return null;
}
思路:
- 首先快慢指针都从起点出发,慢指针每次走一格,快指针每次走两格。
- 快针是慢针走的两倍,因为慢针走的路,快针已经走过一遍。
- 快针走过的剩余路程,也就是和慢针走过的全部路程相等。(a+b = c+b);
- 刨去快针追赶慢针的半圈(b),剩余路程即为所求入环距离(a=c),当他们相遇了,从起点在走一格指针,当它和慢针相遇的时候,就是入环点。
三、总结
- 这道题花了自己一个小时理解清楚,最开始能够快速的通过哈希表完成,但是就是双指针的追逐理解了一会儿。
- 双指针的关键点,当他们追上了,如何去计算出入环的节点。用到数学的相关推理知识。
- 当理解了整个过程之后,代码就好写了。