2 minutes
Week1022_algorithm
ARTS - Algorithm 补12.3
142. 环形链表 II
题目
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:tail connects to node index 1
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:tail connects to node index 0
解释:链表中有一个环,其尾部连接到第一个节点
示例 3:
输入:head = [1], pos = -1
输出:no cycle
解释:链表中没有环。
进阶:
你是否可以不用额外空间解决此题?
分析
这道题是141.环形链表的进阶版,141只要判断是否存在环,这个要求找出进环位置。
首先考虑还是使用HashSet Key的唯一性来做判断,只要第一次存在重复的元素,就说明这个元素为进环位置,代码如下:
public ListNode detectCycle2(ListNode head) {
if (head == null || head.next == null) {
return null;
}
Set<ListNode> set = new HashSet<>();
while (head != null) {
boolean flag = set.add(head);
if (!flag) {
return head;
}
head = head.next;
}
return null;
}
我们需要考虑不增加额外空间来实现这个功能。也参照141环形链表的双指针方案。 思考这样一个链表:
我们假设这个链表 起点、环入口、第一次相遇点 分别是 X, Y, Z, 之间的距离分别是a,b,c
那么,在 Z 点第一次相遇,此时
- 慢指针走的距离为 a+b,
- 快指针走的距离为 a+b+c+b ,
由于快指针速度是慢指针的2倍,也就是说快指针走过的距离为慢指针的距离的2倍,于是就存在以下等式:
2* (a+b) = a+b+c+b
也就是 2a + ab = a+c + 2b,
也就是 a == c
也就是,两个指针第一次相遇点到环入口的距离 和 起点到入口的距离相等,那么我们就可以利用这个特点来写代码。
代码
public ListNode detectCycle(ListNode head) {
if (head == null || head.next == null) {
return null;
}
ListNode fast = head;
ListNode slow = head;
do {
fast = fast.next.next;
slow = slow.next;
} while (fast != null && fast.next != null && fast != slow);
if (fast != slow) {
return null;
}
ListNode p1 = head;
ListNode p2 = slow;
while (p1 != p2) {
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
Read other posts