141. 环形链表
给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos
是 -1
,则在该链表中没有环。
示例 1:
输入:head = [3,2,0,-4], pos = 1 输出:true 解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0 输出:true 解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1 输出:false 解释:链表中没有环。
分析:
设ListNode型的快指针fastNode,慢指针slowNode,遍历链表,慢指针每次走一步,快指针每次走两步,若快慢指针最终相遇,说明存在环,若fastNode != null 或者 fastNode.next != null,说明遍历完毕还是没有遇到,不存在环。
代码:
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
ListNode fastNode = head;
ListNode slowNode = head;
while(fastNode != null && fastNode.next != null){
slowNode = slowNode.next;
fastNode = fastNode.next.next;
if(slowNode == fastNode){
return true;
}
}
return false;
}
}
142. 环形链表 II
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
为了表示给定链表中的环,我们使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos
是 -1
,则在该链表中没有环。
说明:不允许修改给定的链表。
以下图同上:
示例 1:
输入:head = [3,2,0,-4], pos = 1 输出:tail connects to node index 1 解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0 输出:tail connects to node index 0 解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1 输出:no cycle 解释:链表中没有环。
分析:
方法:设ListNode型的快指针fastNode,慢指针slowNode,遍历链表,慢指针每次走一步,快指针每次走两步,若快慢指针相遇,说明存在环,因为遍历完毕而跳出循环,说明没有相遇,没有相遇直接返回null,此时将快指针指向头节点,快、慢指针每次都只走一步,再相遇的节点就是入环的节点。
原因:用以下图来解释这样做为什么会找到入环的节点。
M表示fastNode、slowNode第一次相遇的节点,设头节点到入环节点的距离为a,设入环节点到M节点的距离为b,设慢指针走过的长度是n,那么快指针走过的长度就为2*n,L表示环的长度,且a+b=n; a+b+k*L=2*n;由上式可以推导出k*L=a+b=n;而指针由入环到M走过的长度刚好为b,将fastNode指向head,fastNode到入环节点走a步,slowNode到入环节点走k*L-b=a步。走的步数相同,因此它们再次相遇的节点就是入环节点。
代码:
/**
* 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) {
if(head == null || head.next == null){
return null;
}
ListNode slowNode = head;
ListNode fastNode = head;
//相遇的节点
while(fastNode != null && fastNode.next != null){
slowNode = slowNode.next;
fastNode = fastNode.next.next;
if(slowNode == fastNode){
break;
}
}
if(slowNode != fastNode){
return null;
}
fastNode = head;
while(fastNode != slowNode){
slowNode = slowNode.next;
fastNode = fastNode.next;
}
return slowNode;
}
}