LeetCode.141 环形链表

356 阅读3分钟

这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战

题目描述:

141. 环形链表 - 力扣(LeetCode) (leetcode-cn.com)

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

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

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

进阶:

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

示例一

image.png

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

示例二

image.png

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

示例三

image.png

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

思路分析

节点计数法

最容易的就是遍历链表了,循环访问每个列表,存入HashSet,利用HashSet不可重复的特性,如果我们添加节点失败,就说明这个节点之前添加过,自然就是有环的,反之无环。

AC代码

class Solution {
    fun hasCycle(head: ListNode?): Boolean {
        val set = mutableSetOf<ListNode>()
        var p = head
        while (null != p) {
            if (!set.add(p)) {
                return true
            }
            p = p.next
        }
        return false
    }
}

快慢指针

要判断列表中是否有环,可以定义一个慢指针slow指向链表的头结点,快指针fast指向头结点的下一个结点。然后,慢指针slow每次向前移动一个位置,快指针fast每次向前移动两个位置。这样,如果链表中存在环,快指针就会先进入环,然后追上慢指针。

具体思路,可参考此题解中的动画演示:

AC代码

class Solution {
    fun hasCycle(head: ListNode?): Boolean {
        if (null == head || null == head?.next) {
            return false
        }
        var slow = head
        var fast = head?.next
        while (slow != fast) {
            if (null == fast || null == fast?.next) {
                return false
            }
            slow = slow?.next
            fast = fast?.next?.next
        }
        return true
    }
}

总结

摘自官解

「Floyd 判圈算法」(又称龟兔赛跑算法)

假想「乌龟」和「兔子」在链表上移动,「兔子」跑得快,「乌龟」跑得慢。当「乌龟」和「兔子」从链表上的同一个节点开始移动时,如果该链表中没有环,那么「兔子」将一直处于「乌龟」的前方;如果该链表中有环,那么「兔子」会先于「乌龟」进入环,并且一直在环内移动。等到「乌龟」进入环时,由于「兔子」的速度快,它一定会在某个时刻与乌龟相遇,即套了「乌龟」若干圈。

我们可以根据上述思路来解决本题。具体地,我们定义两个指针,一快一满。慢指针每次只移动一步,而快指针每次移动两步。初始时,慢指针在位置 head,而快指针在位置 head.next。这样一来,如果在移动的过程中,快指针反过来追上慢指针,就说明该链表为环形链表。否则快指针将到达链表尾部,该链表不为环形链表。

如果我们知道这个算法的话,那么要求的进阶答案其实就迎刃而解了。

参考

环形链表 - 环形链表 - 力扣(LeetCode) (leetcode-cn.com)

动画演示 快慢指针 #141环形链表 - 环形链表 - 力扣(LeetCode) (leetcode-cn.com)

扩展阅读

一文搞定常见的链表问题 (欢迎交流 - 环形链表 - 力扣(LeetCode) (leetcode-cn.com)