题目:判断单链表是否有环,如果有则找出环的起点。题目链接
这是另一道题的扩展,利用快慢指针判断出是否有环后,还需要找出环的起点,分析如下:
- 设链表长度为len(链表中非空next指针的个数,下面所说的长度均为非空next指针的个数),链表head到环的起点长度为a,环起点到快慢指针相遇点的长度为b,环的长度为r。
- 假设到快慢指针相遇时,慢指针移动的长度为s,则快指针移动长度为2s,而快指针移动的长度还等于s加上在环上绕的k圈(k>=1),所以2s=s+kr ,即s = kr。
- 由s = a + b 和 s = kr 可知 a + b = kr = (k-1)r + r; 而r = len - a,所以a + b = (k-1)r + len - a, 即 a = (k-1)r + len - a - b,len - a - b是相遇点到环的起点的长度,由此可知,从链表头到环起点长度 = (k-1)环长度+从相遇点到环起点长度,于是我们从链表头、与相遇点分别设一个指针,每次各走一步,两个指针必定相遇,且相遇点为环起点。
代码如下:
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 ListNode *detectCycle(ListNode *head) { 12 // IMPORTANT: Please reset any member data you declared, as 13 // the same Solution instance will be reused for each test case. 14 if(head == NULL || head->next == NULL)return NULL; 15 ListNode *fast = head, *low = head; 16 while(fast != NULL && fast->next != NULL) 17 { 18 low = low->next; 19 fast = fast->next->next; 20 if(low == fast)break; 21 } 22 if(low == fast) 23 {//寻找环的起点 24 fast = head; 25 while(fast != low) 26 { 27 fast = fast->next; 28 low = low->next; 29 } 30 return low; 31 } 32 else return NULL; 33 } 34 };
【版权声明】转载请注明出处: