1.题目描述
给你一个链表的头节点 head
,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos
不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true
。 否则,返回 false
。
提示:
- 链表中节点的数目范围是
[0, 104]
-105 <= Node.val <= 105
pos
为-1
或者链表中的一个 有效索引 。
2.解决思路
这道题目的意思就是,在一个链表中,他的尾节点的下一个节点可能是链表中的其他节点,导致链表中存在环。这是一个简单的思考问题,解决这个问题最容易想到的就是记录下每个遍历到的节点,并每次检查该节点是否已经出现过。不过这个思路虽然可行但时间和空间复杂度都是O(n),因为需要额外的链表长度的空间。第二种方案是利用快慢指针,快指针一开始在前每次移动两格,慢指针在后每次移动一格。如果链表存在环,快指针最终一定会从后面追上慢指针,即使可能套了n圈。因为只使用了额外的两个指针,所以空间复杂度是O(1)。
3.步骤讲解
1.因为存在快指针,所以要首先判断;链表前两个节点是否为空,为空则返回false
2.定义快指针指向头结点下一个节点,和慢指针指向头结点
3.开始循环,条件是快指针和慢指针不重合。当快指针遍历到空时,表示链表不存在环,返回false,否则不断遍历。
4.如果循环退出,快慢指针重合,表示链表存在环,返回true。
4.代码展示
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
public boolean hasCycle2(ListNode head) {
if (head == null || head.next == null){
return false;
}
ListNode slow = head;
ListNode fast = head.next;
while (slow != fast){
if (fast == null || fast.next == null){
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
}
5.执行结果
在leetcode中测试用例平均耗时0ms
内存分布43.45MB