1.题目
给你一个链表的头节点 head
,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos
不作为参数进行传递。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true
。 否则,返回 false
。
2.示例
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:false
解释:链表中没有环
提示:链表中的结构体
java
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
3.思路
快慢指针:
像这种循环题目或者是追逐的题目就可以使用快慢指针算法,由于是循环的,那么除非快指针先找到null的情况下,快慢指针必定相遇,并且两者的相遇也就意味着链表的循环,因为一般情况下快指针是走的快的,慢指针走的慢,而两者速度明显不同的情况下却相遇了,那就说明链表是循环的
哈希集合:
由于循环最后就是查看是否有重合后的地址,那么只需要在往下遍历的时候将链表节点地址保存起来,在下一次遍历的时候如果下一个节点地址已经存在与哈希表中时候,那么也就意味着链表是循环的
4.代码
LeetCode代码
快慢指针:
java
public class Solution {
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) {
return false; // 链表为空或只有一个节点,必然无环
}
ListNode slowIndex = head;
ListNode fastIndex = head;
while (fastIndex != null && fastIndex.next != null) {
slowIndex = slowIndex.next; // 慢指针每次移动一个节点
fastIndex = fastIndex.next.next; // 快指针每次移动两个节点
if (slowIndex == fastIndex) {
return true; // 快慢指针相遇,存在环
}
}
return false; // 快指针到达链表尾部,无环
}
}
时间复杂度O(n),空间复杂度O(1)
哈希集合:
java
public class Solution {
public boolean hasCycle(ListNode head) {
Set<ListNode> set = new HashSet<>();
if(head==null || head.next==null){
return false;
}
while(head.next!=null){
if(set.contains(head)){
return true;
}else{
set.add(head);
head = head.next;
}
}
return false;
}
}
时间复杂度O(n),空间复杂度O(n)
会了?试试挑战下一题!♪(^∀^●)ノシ (●´∀`)♪