LeetCode 142. Linked List Cycle II

来源:互联网 发布:网页数据采集器 编辑:程序博客网 时间:2024/06/05 16:23

142. Linked List Cycle II

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Note: Do not modify the linked list.

Follow up:
Can you solve it without using extra space?

题目内容:
给出一个链表头指针,如果这个链表存在环路,那么找出环路入口节点,并返回这个节点,否则返回NULL。

解题思路:
这个题目是在LeetCode 141. Linked List Cycle的基础上的扩展。所以可以先参考上述连接的方法二来判断是否存在环路,方法二是一种基于追赶的思想,用2个指针slow和fast,slow每次走1个节点,fast每次走2个节点。如果存在环路,当两个指针都进入了环路之后,因为fast每次都比slow多走1个节点,所以每走一次,从fast到slow的距离会越来越小(fast在追赶slow),所以他们总会相遇。所以当slow和fast相遇,那么可以判定存在环路。
那么下一步就是找出环路的入口,首先我们定义以下一些变量:

Sslow:slow
Sfast:fast
C:
L1:
L2:
N:fastslowfast

显然:

Sslow=L1+L2
Sfast=L1+L2+NC

因为fast每次走2个节点,slow每次走2个节点,那么:

2Sslow=Sfast
2L1+2L2=L1+L2+NC
L1+L2=NC
L1=(CL2)+(N1)C,1

如下图:
这里写图片描述
因为在fast和slow相遇之前,fast至少已经在环路里走了一圈,所以N1。所以从公式1,可以看出L1的距离相当于先从相遇点走到环路入口点的距离CL2,再加上在环路走(N1)圈的距离。也就是说,分别从相遇节点和起始节点出发,那么必定会在入口点相遇。
所以当我们用一开始提到的方法找到相遇节点之后,再分别用2个指针从相遇节点和起始节点出发,2个指针每次都只走1个节点,当这2个指针同时访问到同一个节点的时候,那么这个节点就是相遇点。

代码:

/** * Definition for singly-linked list. * struct ListNode { *     int val; *     ListNode *next; *     ListNode(int x) : val(x), next(NULL) {} * }; */class Solution {public:    ListNode *detectCycle(ListNode *head) {        ListNode* fast = head;        ListNode* slow = head;        if (head == NULL) return NULL;        while (true) {            fast = fast->next;            if (fast == NULL) return NULL;            fast = fast->next;            if (fast == NULL) return NULL;            slow = slow->next;            if (slow == fast) break;         }         ListNode* current = head;         while (slow != current) {             slow = slow->next;             current = current->next;         }         return slow;    }};
原创粉丝点击