目录
一 判断有无环
1.1 题目
1.2 示例
1.3 思路及代码
1.3.1 利用哈希表
利用哈希表将每一个节点都存入哈希表中,再存入结点之前,先判断它是否已经存入进哈希表中,如果再次出现则说明有环,反之则没有。
public class Solution {
public boolean hasCycle(ListNode head) {
Set<ListNode> set = new HashSet<ListNode>();
while (head != null) {
if (!set.add(head)) {
return true;
}
head = head.next;
}
return false;
}
}
1.3.2 利用快慢指针
我们定义快慢指针 fast 和 slow,初始时均指向 head。快指针每次走两步,慢指针每次走一步,不断循环。当快慢指针相遇时,说明链表存在环。如果循环结束依然没有相遇,说明链表不存在环。
public class Solution {
public boolean hasCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
return true;
}
}
return false;
}
}
二 返回环的入口
2.1 题目
2.2 示例
2.3 思路及代码
1.3.1 利用哈希表
利用哈希表将每一个节点都存入哈希表中,再存入结点之前,先判断它是否已经存入进哈希表中,如果再次出现则说明有环,反之则没有,第一个重复的就是入口。
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode temp=head;
Set<ListNode>set=new HashSet<>();
while(true) {
if(set.contains(temp)) {
break;
}
else
set.add(temp);
temp=temp.next;
}
return temp;
}
}
1.3.2 利用快慢指针
快慢指针相遇的节点到环形开始的节点的距离就等于头节点到环形开始的节点的距离,所以相遇之后头节点指针和慢指针同时向前移动相遇的地方就是环形开始的节点
public class Solution {
public ListNode detectCycle(ListNode head) {
if (head == null) {
return null;
}
ListNode slow = head, fast = head;
while (fast != null) {
slow = slow.next;
if (fast.next != null) {
fast = fast.next.next;
} else {
return null;
}
if (fast == slow) {
ListNode ptr = head;
while (ptr != slow) {
ptr = ptr.next;
slow = slow.next;
}
return ptr;
}
}
return null;
}
}