【面试算法专栏及回答思考】——环形链表

458 阅读1分钟

这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战

环形链表

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

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

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

示例 1:

img

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

img

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

img

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

链表中节点的数目范围是 [0, 104] -105 <= Node.val <= 105 pos 为 -1 或者链表中的一个 有效索引 。

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

解题

解题思路

老规矩我们先来剖析下做题的思路。这道题不算难,类比龟兔赛跑。若路径有环,兔子绕环跑动终将会和乌龟在同一个节点;若没有环,则兔子到达终点就结束。兔子每次走两步,乌龟每次走一步,分别对用快的节点fastNode和慢的节点slowNode。

为什么fast 走两个节点,slow走一个节点,有环的话,一定会在环内相遇呢,而不是永远的错开呢?首先第一点: fast指针一定先进入环中,如果fast 指针和slow指针相遇的话,一定是在环中相遇,这是毋庸置疑的。

解题步骤

1)定义快慢双指针,slow每次走1步,fast每次走2步 2)先判断head和head.next是否有效,无效返回False 3)slow位于head,fast位于head.next 4)当slow和fast未相遇时,判断fast是否会走到null,如果是返回False, 无法成环 5)当slow和fast相遇时,有环,返回Ture

代码实现

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public var val: Int
 *     public var next: ListNode?
 *     public init(_ val: Int) {
 *         self.val = val
 *         self.next = nil
 *     }
 * }
 */

class Solution {
    func hasCycle(_ head: ListNode?) -> Bool {
        // 快慢指针
        guard head != nil else { return false }
        var slow = head
        var fast = head!.next
        while slow != nil || fast != nil {
            if slow === fast {
                return true
            }
            slow = slow?.next
            fast = fast?.next?.next
        }
        return false
    }
}

关于环形链表的思考和方法今天就分享到这里,同学想看到关于算法面试中的哪些疑难解析,可以给我留言,我们一起再来探讨,我们下篇文章再见。