给你一个链表的头节点 head
,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos
不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true
。 否则,返回 false
。
解题思路:
寻找环:
使用快慢指针法来检测环。
快指针每次移动两步,慢指针每次移动一步。
如果链表中存在环,快指针和慢指针最终会在环内相遇。假设环的长度为 k,链表的非环部分长度为 m,那么在最坏情况下,快指针会在 m + k 步内追上慢指针。
因此,时间复杂度为 O(n),其中 n 是链表的总长度(包括环的部分)。
无环情况:
如果链表中不存在环,快指针会先到达链表末尾(即 p 或 p.next 为 null),此时退出循环。
在这种情况下,时间复杂度也为 O(n),其中 n 是链表的长度。
因此,无论链表中是否存在环,时间复杂度都是 O(n)。
空间复杂度
额外变量:
该方法只使用了两个额外的指针 (p 和 t) 来帮助检测环。
这些变量占用的是常数级别的空间。
因此,空间复杂度为 O(1)。
代码展示:
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
/**
* 检查给定的单链表中是否存在环。
*
* @param head 链表的头节点
* @return 如果链表中存在环则返回 true,否则返回 false
*/
public boolean hasCycle(ListNode head) {
// 初始化两个指针,p 为快指针(每次移动两步),t 为慢指针(每次移动一步)
ListNode p = head; // 快指针
ListNode t = head; // 慢指针
// 当快指针 p 及其下一个节点不为空时,继续循环
while (p != null && p.next != null) {
// 快指针每次移动两步
p = p.next.next;
// 慢指针每次移动一步
t = t.next;
// 如果快指针和慢指针相遇,说明链表中存在环
if (p == t) {
return true;
}
}
// 如果遍历完整个链表,没有发现环,则返回 false
return false;
}
}
标签:head,ListNode,复杂度,环形,next,链表,易懂,指针
From: https://blog.csdn.net/2301_81937222/article/details/144318536