题目描述:
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
思路:
判断是否存在环:
使用追赶的方法,设定两个指针,均从头指针开始,每次分别前进1步、2步。如存在环,则两者相遇;如不存在环,遇到NULL。
找入口:
-
当fast指针等于slow指针时,slow指针肯定还没有遍历完整个链表,而此时fast指针已经在环内循环了n圈(n>=1),假定从链表头指针开始slow走了s步,则fast走了2s步,fast所走的步数还等于s加上fast指针比slow指针在环内多走的n圈。设环长为r,则:
2s = s + nr;
=>s = nr; -
设整个链表长度为L,环的入口结点到相遇结点的距离为x, 起点到环的入口结点的距离为a.
a + x = nr;
=> a + x = (n-1)r + L - a;
=> a = (n-1)r + (L - a - x);
=> 链表的头结点到环入口结点的距离等于n-1圈环的长度+相遇点到环入口结点的距离。 -
于是,当我们在链表头部和相遇处分别设一指针,每次各走一步,则两指针必定相遇,且相遇的第一个结点即为环的入口结点。
代码:
找了半个点bug,发现初始化时,slow和fast指针就都指向头结点,第一个循环的退出条件还是slow == fast。。。猪咩。
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead) {
if (pHead == NULL || pHead->next == NULL || pHead->next->next == NULL) return NULL;
ListNode* slow = pHead->next;
ListNode* fast = pHead->next->next;
while(slow != fast && fast != NULL && fast->next->next != NULL) {
slow = slow->next;
fast = fast->next->next;
}
if (fast == NULL) return NULL;
slow = pHead;
while(slow != fast) {
slow = slow->next;
fast = fast->next;
}
return slow;
}
};
今天又结束了。。。。