题目
找出链表中环的入口节点
给定一个单链表,如果有环,返回环的入口结点,否则,返回null
准备
import java.util.HashSet;
class LishNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
public int getVal() {
return val;
}
}
步骤
方法
Hash
- 遍历链表
- 将节点add到HashSet中
- 判断当前节点的next是否存在于HashSet中如果存在则证明有环。
- 环入口为当前存在于HashSet中的节点
public ListNode hasCycle4HashNode(ListNode head) {
HashSet<ListNode> hashSet = new HashSet<>();
while (head != null) {
if (hashSet.contains(head)) {
return head;
} else {
hashSet.add(head);
head = head.next;
}
}
return null;
}
快慢指针
- 声明快指针和慢指针均为head
- 循环链表配速为慢指针为一步,快指针为2步
- 如果有环的话,快指针肯定会和慢指针相遇
- 相遇之后快慢指针分别走的距离为
- 快:ABCBC
- 慢:ABC
快指针速度为慢指针的二倍所以等量关系计算为:设AB为X,BC为Y 2(X+Y) = X + Y + Y + CB CB = X
所以两指针相遇后,慢指针从C出发,快指针从A出发两者再相遇时的节点则为环入口节点。
public ListNode entryListCycle(ListNode head) {
if (head == null) return null;
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
//快慢指针相遇的节点
if (fast == slow) {
break;
}
}
// 若是快指针指向null,则不存在环
if(fast == null || fast.next == null) return null;
fast = head;
while(fast != slow) {
fast = fast.next;
slow = slow.next;
}
return slow;
}