142. 环形链表 II
难度中等1763
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
示例 1:
输入: head = [3,2,0,-4], pos = 1 输出: 返回索引为 1 的链表节点 解释: 链表中有一个环,其尾部连接到第二个节点。 复制代码
示例 2:
输入: head = [1,2], pos = 0 输出: 返回索引为 0 的链表节点 解释: 链表中有一个环,其尾部连接到第一个节点。 复制代码
示例 3:
输入: head = [1], pos = -1 输出: 返回 null 解释: 链表中没有环。 复制代码
提示:
- 链表中节点的数目范围在范围
[0, 104]
内 -105 <= Node.val <= 105
pos
的值为-1
或者链表中的一个有效索引
进阶: 你是否可以使用 O(1)
空间解决此题?
思路
1.使用标签法,有环必会经过原来标记的的地方,第一次遇到标记过的地方就是环开始的地方 2.使用快慢指针,快指针终会追上慢指针,这样就有环,找到环的长度(指针再多跑一圈)然后2个指针从开头一个先走环长,然后一起同步调前进,等指针遇到时,就是环开始的地方。
/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ /** * @param {ListNode} head * @return {ListNode} */ var detectCycle = function(head) { // 只要结点存在,那么就继续遍历 while(head){ // 如果 flag 已经立过了,那么说明环存在 if(head.flag){ return head; }else{ // 如果 flag 没立过,就立一个 flag 再往下走 head.flag = true; head = head.next; } } return null; }; 复制代码
/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ /** * @param {ListNode} head * @return {ListNode} */ var detectCycle = function(pHead) { if (!pHead || !pHead.next) { return null; } let P1 = pHead.next; let P2 = pHead.next.next; // 1.判断是否有环 while (P1 != P2) { if (P2 === null || P2.next === null) { return null; } P1 = P1.next; P2 = P2.next.next; } // 2.获取环的长度 let temp = P1; let length = 1; P1 = P1.next; while (temp != P1) { P1 = P1.next; length++; } // 3.找公共节点 P1 = P2 = pHead; while (length-- > 0) { P2 = P2.next; } while (P1 != P2) { P1 = P1.next; P2 = P2.next; } return P1; };