给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
不允许修改给定的链表。
是否可以使用 O(1) 空间解决此题?
分析:
首先使用快慢指针方法判断该链表是否有环,如果有环:
假设从起始节点到环入口长度为a,环的长度为r
慢指针已经走过环内的长度为x,环内剩余长度为y
则快慢指针相遇时,慢指针一共走了 a + x
快指针一共走了 a + nr + x
因为快指针速度是慢指针的2倍
则 2(a + x) = a + nr + x,其中r = x + y
则
a + x = nr
==> a + x = (n - 1)r + x + y
==> a = (n - 1)r + y
由此可以得出,如果另外设置两个指针,一个A指针从起始节点走,另一个指针B从快慢指针相遇节点走,则一定和A相遇,相遇节点即为环的入口
代码实现(C):
只需要在判断链表是否有环的代码中,让fast指针指向head,和慢指针一起循环
struct ListNode *detectCycle(struct ListNode *head) {
if (head == NULL) {
return NULL;
}
struct ListNode *fast = head,*slow = head;
while (fast && fast->next) {
slow = slow->next; // 慢指针每次走一步
fast = fast->next->next; // 快指针走两步
if (slow == fast) {
fast = head;
while (fast != slow) { // 两个指针以同样的速度走
fast = fast->next;
slow = slow->next;
}
return slow;
}
}
return NULL
}
代码实现(swift):
extension ListNode : Equatable {
public static func == (lhs: ListNode, rhs: ListNode) -> Bool {
return lhs === rhs
}
}
class Solution {
func detectCycle(_ head: ListNode?) -> ListNode? {
var slow = head
var fast = head
while fast != nil && fast?.next != nil {
slow = slow!.next
fast = fast!.next!.next
if fast == slow {
fast = head
while fast != slow {
fast = fast!.next
slow = slow!.next
}
return fast
}
}
return nil
}
}