LeetCode 142 环形链表 II

连接: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行的判断是不成立的,里面的语句并无执行。仍是要多练习,才能避坑呀。

相关文章
相关标签/搜索