LeetCode:环形链表

1、题目描述

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

提示:

  • 链表中节点的数目范围是 [0, 104]

  • -105 <= Node.val <= 105

  • pos 为 -1 或者链表中的一个 有效索引 。

进阶:你能用 O(1)(即,常量)内存解决此问题吗?

2、方法1:哈希

解题思路

  1. 初始化哈希集合:创建一个 HashSet 来存储已经访问过的节点引用(地址)。

  2. 遍历链表

    • 从链表头节点 head 开始,依次访问每个节点。

    • 对于当前节点 head

      • 如果 head 已经存在于 HashSet 中

        • 说明该节点之前已经被访问过,链表存在环,直接返回 true

      • 如果 head 不在 HashSet 中

        • 将该节点加入 HashSet,表示已经访问过。

        • 移动 head 指针到下一个节点(head = head.next)。

  3. 遍历结束

    • 如果 head 移动到 null,说明链表无环,返回 false

关键点:

  • 哈希集合存储的是节点引用(地址),而不是节点的值(val),因此可以正确处理链表中有重复值的情况。

  • 时间复杂度:O(n),需要遍历整个链表。

  • 空间复杂度:O(n),最坏情况下需要存储所有节点。

代码

//使用哈希set来解题
    public static boolean isCycle(ListNode head){
        if (head == null) return false;
        HashSet<ListNode> visited = new HashSet<>();
        while (head != null){
            if (visited.contains(head)) { //存在,说明已经访问过该节点,说明有环
                return true;
            }
            //无环,将该节点存放到hashset中,并指针下移
            visited.add(head);
            head = head.next;
        }
        return false;  //最后因为循环到null,说明无环,返回false
    }

3、方法2:快慢指针

解题思路

  1. 初始化指针

    • 慢指针 l 指向头节点 head

    • 快指针 r 指向 head.next(初始时快指针比慢指针快一步)。

  2. 遍历链表

    • 循环条件:l != r(即快慢指针未相遇)。

    • 在循环中:

      • 检查快指针是否能移动两步

        • 如果 l.next 和 r.next 均不为 null,则:

          • 慢指针 l 移动一步(l = l.next)。

          • 快指针 r 移动两步(r = r.next.next)。

      • 如果快指针无法移动两步

        • 说明链表无环(因为快指针已经到达链表末尾),直接返回 false

  3. 循环结束

    • 如果退出循环,说明 l == r,即快慢指针相遇,链表存在环,返回 true

关键点

  • 快慢指针的速度差

    • 慢指针每次移动一步,快指针每次移动两步。

    • 如果有环,快指针最终会追上慢指针(类似于跑步套圈)。

  • 无环的判断

    • 如果快指针遇到 null,说明链表无环。

  • 时间复杂度:O(n),快指针遍历速度更快。

  • 空间复杂度:O(1),仅需两个指针,无需额外空间。

代码

//使用快慢指针解题
    public static boolean isCycle1(ListNode head){
        if (head == null) return false;
        ListNode last = head, fast = head;
        while (fast != null && fast.next != null && fast.next.next != null){
            last = last.next;
            fast =  fast.next.next;
            if (fast == last) return true;//当相遇说明有环
        }
        return false;//当退出循环,说明无环
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值