判断链表是否有环---leetcode题目

本文解析LeetCode上两道关于链表环的问题:如何判断链表中是否存在环及如何找到环的入口节点。通过快慢指针技巧,不仅能够高效地解决这些问题,还能深入理解链表环的相关特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分享2道leetcode题目(判断链表是否有环以及找出环的入口点)

141. Linked List Cycle

Given a linked list, determine if it has a cycle in it.

142. Linked List Cycle II

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

第一题就是给你一个链表,让你判断是否有环,如果有返回true,否则返回false

解法过程

1.首先说明链表环的构成:

链表的某个节点的next指针指向到前面的节点,如以下所示
(0->1->2->3->4->5->6->3->4…)

这样子在6节点的后面就会形成无穷无尽的链表,就形成环了。

2.设置分别设置一个快慢指针,快指针运行速度是慢指针的2倍,如果该链表是个环,则快慢指针必相遇,并且相遇是慢指针并没有跑完整个链表长度

快指针设置fast = fast.next.next;

慢指针设置slow = slow.next;

public boolean hasCycle(ListNode head) {
       if(head == null || (head.next == null)) {
           return false;
       }
       ListNode slow = head;
       ListNode fast = head;
       //如果快慢指针相遇,则存在环
       while(fast != null && fast.next != null) {
           slow = slow.next;
           fast = fast.next.next;
            if(fast == slow) {
               return true;
           }
       }
       return false;
    }

第二题就是给你一个链表,如果这个链表有环,则返回环的入口点,如果没有返回null

解法过程
先列出一个有环的链表:
1->2->3->4->5->6->7->8->9->10->3->4…

那答案就是这个链表返回3这个节点

1.顺着第一步分析,快慢指针相遇点是在9这个节点,如果这时候在9这处放置一个指针,在头节点处放置一个指针,让他们同时以相同的速度移动,则很恰巧他们是在3这个环的入口点相遇,这是巧合吗。接下来就要验证该方法是否可行。

设置链表长度为L,入口点距离头节点距离为a,快慢指针相遇点距离入口点为b,满指针速度为s,环的长度为r,则可以得到以下公式:

2s = s + nr (n为环的圈数)

s = a + b (慢指针从头节点走到相遇点)

r = L - a

2.则我们可以把公式变形成如下

a + b = nr

a = nr -b

a = (n-1)r + r - b

a = (n-1)r + (L -a -b)

这个公式可以得出a就是环入口距离头节点的距离,(n-1)r是(n-1)圈的环,(L-a-b)其实就是相遇点到环入口的距离

那其实可以得出如果一个指针从相遇点出发,则一定会跟一个从头指针出发的指针相遇,并且相遇点 就是环的入口点

3.那么解法就很简单了

public ListNode detectCycle(ListNode head) {
        if(head == null || (head.next == null)) {
           return null;
       }
       ListNode slow = head,fast = head;
       ListNode start = head;
       ListNode end = null;
       //快慢指针找到相遇点
       while(fast != null && fast.next != null) {
           slow = slow.next;
           fast = fast.next.next;
            if(fast == slow) {
               end = fast;
               break;
           }
       }
       if(end == null || end.next == null ){
           return null;
       }
       //这时重新在相遇点跟head出设置指针,然后同时走一步,则相遇点就是环入口
       while(start != end) {
           start = start.next;
           end = end.next;
       }
       return start;
    }

谢谢欣赏!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值