2025年- H38-Lc146 --142.环形链表(快慢指针,快2慢1,快1慢1)--Java版
1.题目描述
2.思路
第一步:判断是否有环
快慢指针(fast 每次走 2 步,slow 走 1 步);
如果 fast == slow,说明有环;
第二步:找环的起始节点
两指针:一个从头走,一个从相遇点走,每次走一步;
相遇点就是入环节点。
补充:
(1)在本题的求解过程中,双指针会产生两次“相遇”。
双指针的第一次相遇:
设两指针 fast,slow 指向链表头部 head 。
令 fast 每轮走 2 步,slow 每轮走 1 步。
(2)双指针第二次相遇:
令 fast 重新指向链表头部节点。此时 f=0,s=nb 。
slow 和 fast 同时每轮向前走 1 步。
当 fast 指针走到 f=a 步时,slow 指针走到 s=a+nb 步。此时两指针重合,并同时指向链表环入口,返回 slow 指向的节点即可。
模拟指针两次相遇的动态图
3.代码实现
class ListNode {int val;ListNode next;public ListNode() {}ListNode(int x) {val = x;next = null;}public ListNode(int val, ListNode next) {this.val = val;this.next = next;}}
public class H142 {public ListNode detectCycle(ListNode head) {ListNode slow=head;ListNode fast=head;//一开始要同起点出发//1.存在空节点或者一个节点的,返回nullif(head==null||head.next==null){return null;}//3.开始执行快2慢1的操作while(fast!=null&&fast.next!=null)//不能是链表的情况,要同时存在。{fast=fast.next.next;slow=slow.next;if(fast==slow)//第一次相遇,说明存在环。快慢指针一起从原点出发{//第二次相遇,快慢指针每次走一步fast=head;//第二次相遇快指针从head开始走while(fast!=slow)//用if和while都可以,说明p1和p2 第二次还没相遇{fast=fast.next;slow=slow.next;}return fast;//如果p1=p2,说明此时快慢指针相遇。第二次相遇过程,慢指针叫p2,快指针叫p1}}return null;//说明无环}public static void main(String[] args){H142 test = new H142();// 构建链表:3 -> 2 -> 0 -> -4ListNode node4 = new ListNode(-4);ListNode node3 = new ListNode(0, node4);ListNode node2 = new ListNode(2, node3);ListNode head = new ListNode(3, node2);// 构建环:让 -4 指向 2,形成环node4.next = node2;ListNode res = test.detectCycle(head);System.out.print("输出返回链表开始入环的第一个节点的结果;");if (res != null) {System.out.print(res.val);}else{System.out.print("无环");}}}