给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是
-1,则在该链表中没有环。示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
1.快慢指针
可以类比成两个运动员 在同一个环形运动场跑步,一个跑的快的 和 一个跑的慢的 在一定的时间内 快的一定会和慢的相遇,这个时候 就说明 有环存在。
//检查是否链表中有环
//思路:定义一个快指针 和 一个慢指针 慢指针一次走一步 快指针一次走两步
//如果有环 一定会相遇。多次循环
public boolean hasCycle(ListNode head) {
if (head == null){
return false;
}
ListNode fastNode = head.next;
ListNode slowNode = head;
while (fastNode!=null && fastNode.next!=null){
fastNode = fastNode.next.next;
slowNode = slowNode.next;
if (slowNode == fastNode)
return true;
}
return false;
}
分析:
时间复杂度:o(n)
1.第一种情况 链表不存在环 快慢指针分别到达尾部,其时间取决于列表的长度。O(n)
2.第二种情况 链表中存在环 在最糟糕的情形下,时间复杂度为 O(N+K)O(N+K),也就是 O(n)
空间复杂度 o(1)
只是用了快慢指针两个结点。
2.哈希表
思路: 通过创建哈希表,遍历链表 将每次遍历的都存储到哈希表中 如果哈希表中有当前哈希值 说明 遍历到了环形处,说明是环形链表 否则的话 遍历完 说明不是环形链表
public boolean hasCycle2(ListNode head) {
Set nodeSet = new HashSet();
while (head!=null){
if (nodeSet.contains(head)){
return true;
}
nodeSet.add(head);
head = head.next;
}
return false;
}
时间复杂度:o(n) 对于含有n个元素的链表
空间复杂度: o(n) 最坏情况下 全部添加 所有取决于哈希表中的元素数目