给定一个链表,判断链表中是否有环。
思路一:
通过一个哈希表,在向后遍历时每遍历一个就加进去,然后判断这个节点之前是否添加过。如果从头到尾都没有则不是环形,有的话就是。
- 时间复杂度:O(n),对于含有 n个元素的链表,我们访问每个元素最多一次。添加一个结点到哈希表中只需要花费 O(1)的时间。
- 空间复杂度:O(n),空间取决于添加到哈希表中的元素数目,最多可以添加 n 个元素。
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
HashSet<ListNode> set = new HashSet<ListNode>();
while(head!=null){
if(set.contains(head)){
return true;
}
set.add(head);
head = head.next;
}
return false;
}
}
思路二:
使用双指针,一个跑得快,一个跑得慢。如果有环的话,那么跑的快的一定会追上跑的慢的。如果到头都没有追上,那么就没有环。
- 时间复杂度:O(n)。没有环便直接到头;如果有环,在环内部两者速度差1,距离假设为k,则耗时K即可追上。
- 空间复杂度:O(1),我们只使用了慢指针和快指针两个结点,所以空间复杂度为 O(1)。
public class Solution {
public boolean hasCycle(ListNode head) {
if(head==null || head.next==null){
return false;
}
ListNode slow = head;
ListNode fast = head.next;
while(fast!=null && fast.next!=null){
if(slow==fast){
return true;
}
slow = slow.next;
fast = fast.next.next;
}
return false;
}
}