力扣-142-环形链表II

83 阅读2分钟

142. 环形链表 II

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

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

示例 1:

输入: head = [3,2,0,-4], pos = 1
输出: 返回索引为 1 的链表节点
解释: 链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入: head = [1,2], pos = 0
输出: 返回索引为 0 的链表节点
解释: 链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入: head = [1], pos = -1
输出: 返回 null
解释: 链表中没有环。

方法一:暴力

思路:

1、遍历整个链表,如果当前结点未被记录,将其记录;若有记录(即指向同一结点)返回当前结点;

2、如果遍历完整个链表,只是记录了每个结点,则返回null(即无环)

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        vector<ListNode*> a;
        while(head){
            for(int i=0;i<a.size();i++){
                if(a[i]==head){
                    return head;
                }
            }
            a.push_back(head);
            head=head->next;
        }
        return NULL;
    }
};

方法二:借助哈希容器

思路:同方法一

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

方法三:快慢指针

思路:

1、令fast、slow(快慢指针)指向头结点(fast每次走两步,slow每次走一步),先默认有环

2、第一次相遇(此次相遇一定在环内,因为fast总是会比slow先到环内)

3、第二次相遇(此次相遇在入环点。当在第一次相遇后,根据fast和slow的2倍关系可知,相遇点到入环点的距离加n-1圈的环长,恰好等于链表头到入环点的距离,具体见下方),此时返回第二次相遇点即可

4、若最后fast或fast->next指向空(即无环),返回空

附:设a为head到入环点距离,b为入环点到第一次相遇点的距离,c为第一次相遇点到入环点的距离,则 a+(n-1)b+c=2(a+b)====> a=c+(n-1)(b+c),即最终会在入环点相遇

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *fast=head,*slow=head;
        while(fast!=NULL&&fast->next!=NULL){
            fast=fast->next->next;
            slow=slow->next;
            if(slow==fast){
                ListNode *per=head;
                while(per!=slow){
                    per=per->next;
                    slow=slow->next;
                }
                return per;
            }
        }
        return NULL;
    }
};
};