连接:https://leetcode-cn.com/problems/linked-list-cycle-iinode
给定一个链表,返回链表开始入环的第一个节点。 若是链表无环,则返回 null。c++
为了表示给定链表中的环,咱们使用整数 pos 来表示链表尾链接到链表中的位置(索引从 0 开始)。 若是 pos 是 -1,则在该链表中没有环。函数
说明:不容许修改给定的链表。spa
示例 :指针
输入:head = [3,2,0,-4], pos = 1
输出:tail connects to node index 1
解释:链表中有一个环,其尾部链接到第二个节点。code
这道题的解法十分巧妙,只能膜拜。。用到了快慢指针,让快慢指针同时走,可是快指针一次走两步,慢指针一次走一步。能够想象,当慢指针走到出现环的交点时,快指针已经走到环中的某个位置了。假设慢指针走了x步到达交点,那么快指针此时已经走了2x步。假设快指针还要走y步再次到达交点,那么当慢指针从交点出发再走y步时,快慢指针相遇,这是由于快指针的速度是慢指针的2倍。当快慢指针相遇时,让慢指针指向头节点,快指针依然在相遇的位置,这时让快慢指针都是一次走一步,那么当快慢指针再次相遇的时候,就是所求的出现环的交点。这是由于,慢指针从头节点走x步到达交点,和以前同样。而快指针从相遇位置也是再走x步到达交点。blog
这道题画个图就很清楚,环的位置实际上是求快慢指针再次相遇时所在位置。索引
若是不存在环,那么快慢指针不会走到环中去,因为快指针走的快,因此它会一直走到空。当出现空的时候,说明不存在环,函数直接返回空就好。leetcode
c++代码以下:io
1 class Solution { 2 public: 3 ListNode *detectCycle(ListNode *head) { 4 auto slow = head, fast = head; 5 while(fast){ 6 fast = fast->next; 7 slow = slow->next; 8 if(fast){ 9 fast = fast->next; 10 } 11 else break; 12 13 if(fast == slow){ 14 slow = head; 15 while(fast != slow){ 16 fast = fast->next; 17 slow = slow->next; 18 } 19 return slow; 20 } 21 } 22 return NULL; 23 } 24 };
在写代码的时候,出现了一个bug,看了很久才看出来,错误代码以下:
1 class Solution { 2 public: 3 ListNode *detectCycle(ListNode *head) { 4 auto slow = head, fast = head; 5 while(fast){ 6 if(slow != fast){ 7 slow = slow->next; 8 fast = fast->next; 9 if(fast){ 10 fast = fast->next; 11 } 12 else break; 13 } 14 else{ 15 slow = head; 16 while(slow != fast){ 17 slow = slow->next; 18 fast = fast->next; 19 } 20 return fast; 21 } 22 } 23 return NULL; 24 } 25 };
思路是同样的,当快慢指针没有相遇的时候,两个指针以不一样的速度向前走,直到相遇时让慢指针回到头节点再开始走,直到快慢节点在交点相遇。区别在于第二个代码先判断了快慢指针是否相遇,而在初始化时快慢指针都指向头节点,因此第6行的判断是不成立的,里面的语句并无执行。仍是要多练习,才能避坑呀。