leecode142题题解

原题
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

说明:不允许修改给定的链表。

解题思路
两个关键点:该链路是否为环路,如果是的话,环路起始点在哪里?
1.判断是否有环路。用一个指针遍历结点,如果能走到头即没有回路(注意链路可能为空,所以不光要看fast->next,还要看fast是否为NULL),如果一直往下走即为有回路。
这里就会出现一个问题,有回路就会陷入死循环,解决方法就是使用快慢双指针。fast每次前进两步,
slow每次前进一步,如果能相遇即为有回路,不然慢指针永远追不上快指针(起始点都一样,所以不要用while循环)。快慢指针为何一定相遇,知乎上有用户进行了解答,一下是知乎上的解释:
1:快指针与慢指针之间差一步。此时继续往后走,慢指针前进一步,快指针前进两步,两者相遇。
2:快指针与慢指针之间差两步。此时继续往后走,慢指针前进一步,快指针前进两步,两者之间相差一步,转化为第一种情况。
3:快指针与慢指针之间差N步。此时继续往后走,慢指针前进一步,快指针前进两步,两者之间相差(N+1-2)-> N-1步。因此,此题得证。所以快指针必然与慢指针相遇。又因为快指针速度是慢指针的两倍,所以相遇时必然只绕了一圈。

作者:知乎用户
链接:https://www.zhihu.com/question/23208893/answer/117115415
2.环路起始点在哪里。
将fast和slow的步进都设为1,这样 相遇点必然是链路入口,不然步长一样其他地方不会相遇(当然,此时fast和slow是相遇的,需要将其拉开,将fast重新指向头结点,如果slow此时也在这,那么头结点就是入口)。相遇点一定是回路入口,但是可能有人会担心,快慢指针是不是必然会相遇,有人也对此做了证明:若在头结点和相遇结点分别设一指针,同步(单步)前进,则最后一定相遇在环入口结点p。https://www.cnblogs.com/songdechiu/p/6686520.html

/**
 * 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,*slow;
   fast=slow=head;
   do
   {
	   if(fast==NULL ||fast->next ==NULL )
		   return nullptr ;
	   fast=fast->next ->next ;
	   slow=slow->next ;
   }while(fast!=slow);

   fast=head;
   while(fast!=slow)
   {
        fast=fast->next ;
		slow=slow->next ;
   }
   return fast;
    }
};

你可能感兴趣的:(C++)