题目描述:给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos
是 -1
,则在该链表中没有环。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。示例 2:
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。示例 3:
输入:head = [1], pos = -1
输出:false
解释:链表中没有环。进阶:你能用 O(1)(即,常量)内存解决此问题吗?
1 | /** |
方法一:快慢指针
我们可以巧妙的使用快慢指针来模拟追击问题,只要存在环状结构,就一定可以追上。
- 创建两个指针,P1(快指针)和P2(慢指针),并且同时指向链表的头结点。
- 遍历链表,每遍历一个节点,指针P1向下移动两个节点,指针P2向下移动一个节点。(为什么移动两个节点:在快的快追上慢的时,他们之间一定只差1个或者2个节点,如果落后1个,那么下一次就能追上。如果落后2个,那么下一次就落后一个,再下一次就能追上,所以快指针可以设置成2)
- 如果链表遍历结束之前,指针指向同一节点,则说明链表有环
1 | public class Solution { |
复杂度分析:
时间复杂度:遍历链表O(n)
空间复杂度:除了两个指针,没有使用额外的存储空间,所以空间复杂度为O(1)
执行结果:通过
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:39.9 MB, 在所有 Java 提交中击败了59.68%的用户
方法二:哈希表
遍历链表,使用hashset来存储节点,每遍历一个节点,就判断hashset中是否已存在此节点,如果存在则说明节点有环。如果不存在,就将新节点存到hashset中,重复上述步骤。
1 | public class Solution { |
复杂度分析:
时间复杂度:O(n)
空间复杂度:使用了额外的存储空间,所以空间复杂度为O(n)
执行结果:通过
- 执行用时:4 ms, 在所有 Java 提交中击败了22.81%的用户
- 内存消耗:40.3 MB, 在所有 Java 提交中击败了13.69%的用户