题目
思路一:HASH
第一反应就是用hash,遍历链表,将节点都存储到Set中,并判断当前节点的下一个节点是否存在于Set集合中,如果存在,肯定就是环啦;
public class Solution {
public boolean hasCycle(ListNode head) {
Set<ListNode> nodes = new HashSet<ListNode>();
ListNode tempNode = head;
while(tempNode != null){
if(nodes.contains(tempNode)){
return true;
}
nodes.add(tempNode);
tempNode = tempNode.next;
}
return false;
}
}
时间复杂度:O(N),最坏情况是,将链表的每个节点都访问一次;
空间复杂度:O(N),最坏情况是,将链表的每个节点都添加到Set中;
思路二:使用快慢指针
理解:可以将链表想象成环形跑道,跑步速度快的人什么时候会和跑步慢的人相遇,答案是扣圈哈哈哈;如果是直线跑道,两个人怎样都不会相遇。
链表同理,快慢指针开始都指向头节点,之后slow向后走一步,fast向后走两步,如果链表是环,那么两个速度不同的指针必定会相遇
图解步骤:
初始两个指针都指向头节点;
slow向前走一步,指向2;fast向前走两步,指向3;
slow向前走一步,指向3;fast向前走两步,指向2;
slow向前走一步,指向4;fast向前走两步,指向4;此时,slow被扣圈,两个指针相遇。
public class Solution {
public boolean hasCycle(ListNode head) {
ListNode slow = head, fast = head;
//fast比slow快,fast不是空则slow一定也不是空,所以只需对fast做判断即可
//小tips:可能有人拿不准什么时候判断next,什么时候判断next.next
//技巧是统一对上一级做判断:比如:要使用那next,则对本身做判断;要使用next.next,则对next做判断
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
if(slow == fast){
return true;
}
}
return false;
}
}
时间复杂度:O(N);
空间复杂度:O(1),只使用了两个指针;
看到此处即是情,别忘记点个赞哦。如果有其他问题,欢迎评论,共同探讨!!!