链表中环的入口节点
链表中环的入口节点
给定一个链表,返回链表开始入环的第一个节点。
从链表的头节点开始沿着 next
指针进入环的第一个节点为环的入口节点。如果链表无环,则返回 null
。
- 为了表示给定链表中的环,我们使用整数
pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。 - 如果
pos
是-1
,则在该链表中没有环。 - 注意
pos
仅仅是用于标识环的情况,并不会作为参数传递到函数中。 - 说明:不允许修改给定的链表。
1.哈希表
思路:
- 利用哈希表建立一个标记数组 用于标记已经出现的next指针域
- while循环遍历链表 直到出现重复的next指针域 表示链表环开始出现
- 返回此时的链表结点指针 即为环入口结点
unordered_map
1 | class Solution { |
时间:12ms
内存:9.8mb
unordered_set
1 | public: |
时间:8ms
内存:9.3mb
复杂度
- 时间复杂度:$O(N)$ 需要访问链表中的每一个结点
- 空间复杂度:$O(N)$ 需要将链表中的结点保存在哈希表当中
2.双指针
相似问题:寻找距离尾部第k个结点、寻找环入口、寻找公共尾部入口
大致思路:
- 使用两个指针fast与slow从链表头部开始
- slow指针每次向后移动一个位置 fast指针每次向后移动两个位置
- 如果链表中存在环 则fast指针最终将会再次与slow指针相遇
详细步骤:
双指针第一次相遇:fast、slow指向链表头部head; fast每轮走2步、slow每轮走1步
- case1:fast指针走过链表末端 说明链表中无环 直接返回nullptr
- case2:当fast==slow时两指针在环中第一次相遇 分析fast与slow走过的步数关系
- 设链表共有 a + b 个结点 其中链表头部到链表入口有a个结点 链表环中有b个结点,设两个指针分别走了f、s步则有:
- fast走的步数为slow的两倍 f = 2s
- fast比slow多走了n个环的长度 f = s + nb (n为整数)
- 相减得到 f = 2nb s = nb(fast和slow指针分别走了 2n 和 n 个环的周长)
双指针第二次相遇:
- slow指针位置不变 将fast指针重新指向链表头结点
- slow 和 fast 同时每轮向前走1步
- 当fast指针走到 f = a 步时 slow指针走到步 s = a + nb 此时两指针重合并同时指向环入口
- 第2次相遇后返回slow指针指向的结点即可
encounter1
encounter2
reference
1 | class Solution { |
时间:4ms
内存:7.4mb
复杂度
- 时间复杂度:$O(N)$
- 空间复杂度:$O(1)$
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.