142. Linked List Cycle II。

来源:互联网 发布:移动免费流量软件 编辑:程序博客网 时间:2024/05/21 06:12

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Note: Do not modify the linked list.

Follow up:
Can you solve it without using extra space?


是141. Linked List Cycle。的升级版本。需要找出进入环的那个节点所在。第一种还是使用之前的集合方法,定义一个set集合并遍历链表,如果当前节点不存在set中则将节点存放进去,如果存在了这说明这个节点就是进入环的位置。

class Solution {public:    ListNode *detectCycle(ListNode *head) {        unordered_set<ListNode*> nodes;        while(head) {            if(nodes.count(head)==1) {                return head;            } else {                nodes.insert(head);            }            head = head->next;        }        return NULL;    }};

第二种使用的是赋值的方法,遍历每个节点,然后将节点的值赋值为INT_MAX,那么遇到下一次的节点值等于INT_MAX时候就是环的入口。

class Solution {public:    ListNode *detectCycle(ListNode *head) {        while(head) {            if(head->val != INT_MAX) {                head->val = INT_MAX;            } else {                return head;            }            head = head->next;        }        return NULL;    }};

第三种是使用快慢指针的方法,先来画一个图。

这里写图片描述

图中分为了三个阶段A为链表的起点,B为环的入口,如果使用快慢指针的话,快的指针先进入环,然后慢的指针进入。这个时候可以看成快的指针在追赶慢的指针,假设快指针在C处追到了慢指针。此时相当于是快指针已经饶了环一圈了,那么快指针走的路就是1+2+3+2,而慢指针走的路是1+2。并且因为快指针走的路是慢指针的两倍,所以能够得出3=1.既然1和3的路是相等的,就可以使用两个指针分别从A点和C点出发,当他们相遇的时候就是走了图中1(或者3)的距离,而从链表的起点A到环的入口点B正好距离就是1,所以此时相遇的节点就是环的入口。

class Solution {public:    ListNode *detectCycle(ListNode *head) {        //快慢指针        if(!head) return nullptr;        ListNode* slow = head;        ListNode* fast = head;        ListNode* entry = head;        while(fast->next && fast->next->next) {            fast = fast->next->next;            slow = slow->next;            if(fast == slow) {                while(entry != slow) {                    entry = entry->next;                    slow = slow->next;                }                return entry;            }        }        return nullptr;    }};