哈希表
解题思路:
- 定义一个node结点指向头结点
- 定义一个哈希表
- 以node不为空为条件循环链表
- 如果node结点已经存在于哈希表中,说明链表有环并且返回该node结点在链表中的位置
- 否则node并不存在于哈希表中,将node添加到哈希表,node往后移动一个结点
- 若循环执行结束,说明链表中不存在环,返回null
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode node = head;
HashSet<ListNode> set = new HashSet<ListNode>();
while(node != null){
if(set.contains(node)){
return node;
}
set.add(node);
node = node.next;
}
return null;
}
}
快慢指针
解题思路:
- 若头结点为空或者头结点下一节点为空,则链表无环返回null
- 分别定义一个快指针和一个慢指针,都指向头结点
- 以fast不为空作为条件循环遍历链表
- 若快指针为空或者快指针下一节点为空,则链表无环返回null
- 慢指针往后移动一个节点,快指针往后移动两个节点
- 如果此时快慢指针相等,也就是链表有环;定义一个指向头结点的新结点node,以node结点和慢指针不相等为条件执行循环体,node结点和慢指针每次移动一个结点,当循环结束时,说明node和慢指针相遇,并且它们走过的距离恰好是链表环的第一个结点,返回node结点
- 外层while循环顺利执行结束,说明链表不存在环,返回null
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head == null || head.next == null) return null;
ListNode fast = head;
ListNode slow = head;
while(fast != null){
if(fast == null || fast.next == null){
return null;
}
slow = slow.next;
fast = fast.next.next;
if(fast == slow){
ListNode node = head;
while(node != slow){
node = node.next;
slow = slow.next;
}
return node;
}
}
return null;
}
}