领扣(leetcode)

环形链表 II

2018-09-16  本文已影响0人  莫小鹏

题目描述

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

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

进阶:
你是否可以不用额外空间解决此题?

分析

用双指针遍历求相交的节点。
慢指针和快指针的初始位置是:head
慢指针一次前进一步,快指针一次前进两步。
两个指针相交的节点为C。
设非循环链表部分为X,循环链表中C节点之前的部分为Y ,C之后的部分为Z,可以根据快指针和慢指针经过的节点数列出方程:
2*(X + Y) = X + Y + Z + Y
解方程得到:X = Z
让慢指针从C节点出发,快指针从head出发,一次前进一步,相等的节点为入环的第一个节点
方程左边的慢指针遍历的节点数,右边为快指针遍历的节点数,
链表:
1 -> 2 -> 3 -> 4,循环节点为3,
慢指针遍历的节点是:2,3
快指针遍历的节点是:2,3,4,3
起始位置的节点不算
相交的节点是:3
X = 2
Z = 4
Y = 3

代码

/**
 * 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) {
        if(head == NULL) {
            return NULL;
        }
        auto slow = head;
        auto quick = head;
        bool circle = false;
        while(quick != NULL && quick->next != NULL) {
            slow = slow->next;
            quick = quick->next->next;
            if(quick == slow){
                circle = true;
                break;
            }
        }
        if(!circle) {
            return NULL;
        }
        quick = head;
        while(slow != quick) {
            slow = slow->next;
            quick = quick->next;
        }
        return slow;
    }
};

题目链接

https://leetcode-cn.com/explore/interview/card/tencent/222/linked-list/917/

上一篇下一篇

猜你喜欢

热点阅读