判断单链表是否有环(java)

本文介绍了如何通过快慢指针判断单链表中是否存在环。当快指针和慢指针相遇时,即可确定链表有环。具体实现代码中,通过不断移动快慢指针,当快指针的next不为空且next的next也不为空时,更新它们的位置。若两者相遇则返回true,否则返回false。该方法巧妙地解决了链表环的检测问题。

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

图示

  • 一般而言的单链表的尾部结点的next域指向null,是没有环的;
    在这里插入图片描述

  • 当单链表的尾部结点的next域指向其前面任一结点时,则证明链表有环。
    在这里插入图片描述

思路分析

  • 定义两个指针,快指针和慢指针,快指针步长为2,慢指针步长为1。
  • 如果链表有环,则两个指针一定可以在环内相遇(为什么?可以很明确的一点是,如果链表没有环,两个指针永远不会相遇。接下来只需要证明在有环的情况下,两个指针一定会相遇,证明见图解2
  • 图解
  1. 特例
    在这里插入图片描述

  2. 两指针一定会相遇的证明
    在这里插入图片描述
    以fast为起点,把环想象成一个无限延伸的直线,问题转换为直线距离的追及问题,直到fast追上slow为止。
    在这里插入图片描述

    ① 假设fast和slow相距x,fast速度为2,slow速度为1,时间t后,两者相遇
    则一定有t+x = 2t => x = t,换言之就是,两者相距x,再移动x次就追上了
    在这里插入图片描述
    ② 再回到环,一定有 x属于[0,L),所以经过有限次移动一定可以相遇

代码实现

public static boolean hasCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while (fast.next != null && fast.next.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {
                return true;
            }
        }
        return false;
    }
### Java单链表检测算法 在Java中,判断单链表是否存在可以通过快慢指针法实现。这种方法基于两个指针以不同速度遍历链表的原理。如果链表存在,则两个指针会在某一时刻相遇;否则,其中一个指针会先到达链表末尾[^1]。 以下是具体实现代码: ```java public class ListNode { int val; ListNode next; ListNode(int val) { this.val = val; this.next = null; } } public class Solution { 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 (slow == fast) { // 如果快慢指针相遇,则存在 return true; } } return false; // 如果快指针到达链表末尾,则不存在 } } ``` #### 算法分析 - **时间复杂度**:O(n),其中n为链表中的节点数。快慢指针最多遍历整个链表一次[^2]。 - **空间复杂度**:O(1),仅使用了两个额外的指针变量(`slow`和`fast`)[^3]。 #### 入口点检测 除了判断链表是否存在外,还可以进一步找到的入口点。以下是实现代码: ```java public ListNode detectCycle(ListNode head) { ListNode slow = head, fast = head; boolean hasCycle = false; while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; if (slow == fast) { hasCycle = true; break; } } if (!hasCycle) { return null; // 无 } slow = head; while (slow != fast) { slow = slow.next; fast = fast.next; } return slow; // 返回的入口点 } ``` 此方法通过将慢指针重新指向头节点,并与快指针以相同速度前进,最终两者会在的入口点相遇。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值