给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
集合法
创建一个集合,循环链表节点,直到最后一个节点的next=null,期间判断集合中是否存在同样的节点,不存在就把节点放入集合,存在就直接返回true,说明存在循环链表,如果到最后一个节点都没包含,那么说明没有循环,返回false
public class Solution {
public boolean hasCycle(ListNode head) {
List<ListNode> nodesSeen = new ArrayList<>();// 创建一个集合,循环链表节点
while (head != null) {//期间判断集合中是否存在同样的节点,不存在就把节点放入集合,存在就直接返回true,说明存在循环链表,
if (nodesSeen.contains(head)) {
return true;
} else {
nodesSeen.add(head);
}
head = head.next;
}
return false;//如果到最后一个节点都没包含,那么说明没有循环,返回false
}
}
快慢指针法:
可以想象成跑步,两个人(指针),一个速度快,一个慢,如果在直线跑道,那么两人永远不会相遇,如果在环形跑道,那么两个人一定会相遇
此时退出条件要注意,first由于是两步,所以可能是最后一个节点(first.next=null),还有可能是最后一个节点的下一个节点(first=null)
public boolean hasCycle(ListNode head) {
ListNode first = head;
ListNode slow = head;
while(first!=null&&first.next!=null){
first=first.next.next;
slow=slow.next;
if(first==slow){return true;}
}
return false;
}
}
- 提高:返回进入循环的节点
public class Solution {
public ListNode detectCycle(ListNode head) {
Set<ListNode> nodeSet = new HashSet<>();
ListNode temp = head;
if (head == null) {
return null;
} else {
while (temp.next != null) {
if (nodeSet.contains(temp)) {
return temp;
} else {
nodeSet.add(temp);
temp = temp.next;
}
}
return null;
}
}
}