(LeetCode-141)环形链表

文章介绍了如何使用Floyd环判定算法解决链表中是否存在环的问题,以及常规的Hash表方法。重点在于提供了一种O(1)内存复杂度的解决方案,适用于进阶要求。
摘要由CSDN通过智能技术生成

题目

给定个链表,判断链表中是否有环。

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

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

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

示例 1:

输入:head = [3,2,0,-4], pos = 1

输出:返回索引为 1 的链表节点

解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0

输出:返回索引为 0 的链表节点

解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入:head = [1], pos = -1

输出:返回 null

解释:链表中没有环。

 提示:

链表中节点的数目范围在范围 [0, 104] 内

-105 <= Node.val <= 105

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

分析和解答

方法1

可以使用Hash表来解决:

1、从表头结点开始,逐个遍历链表中的每个结点。

2、对于每个结点,检查该结点的地址是否存在于散列表中。

3、如果存在,则表明当前访问的结点已经被访问过了。出现这种情况只能是因为给定链表中存在环。

4、如果散列表中没有当前结点的地址,那么把该地址插入散列表中。重复上述过程,直至到达表尾或者找到环。

这个方法时间复杂度为O(n),用于扫描链表。空间复杂度为O(n),用于散列表的空间开销。

但是题目进阶要求是能用 O(1)内存解决此问题,所以这个方法我们不做具体实现,留给同学们自行实现。

方法2

对于判断是否存在环形链表,其实存在着一种通用解法,该方法称为Floyd环判定算法。该方法使用两个在链表中具有不同移动速度的指针。一旦它们进入环,就成为一个环形追及问题,两者肯定相遇,只要相遇就表示存在环。

在工程实践中,一般两个指针每次分别移动1个结点和2个结点,其他的移动速度也能解决这个问题,但是会增加算法的复杂度。

代码


/**
 * @author :
 * @description :(LeetCode-141) 环形链表
 * 给定个链表,判断链表中是否有环。
 * 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。
 * 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。
 * 如果 pos 是 -1,则在该链表中没有环。
 * 注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
 * 如果链表中存在环,则返回 true 。 否则,返回 false 。
 * 进阶:你能用 O(1)内存解决此问题吗?
 */
public class LinkedListCycle_141 {

    public boolean hasCycle(ListNode head) {
        if (head == null)  return false;
        ListNode slowPtr = head, fastPtr = head;
        while (fastPtr.next != null && fastPtr.next.next != null) {
            slowPtr = slowPtr.next;
            fastPtr = fastPtr.next.next;
            if (slowPtr == fastPtr)
                return true;
        }
        return false;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值