这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战
环形链表
给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意: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)(即,常量)内存解决此问题吗?
解题
解题思路
老规矩我们先来剖析下做题的思路。这道题不算难,类比龟兔赛跑。若路径有环,兔子绕环跑动终将会和乌龟在同一个节点;若没有环,则兔子到达终点就结束。兔子每次走两步,乌龟每次走一步,分别对用快的节点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
}
}
关于环形链表的思考和方法今天就分享到这里,同学想看到关于算法面试中的哪些疑难解析,可以给我留言,我们一起再来探讨,我们下篇文章再见。