#15环形链表 II#

1°题目链接

链接

2°思路

思路1(结论):

如何求环的入口点
结论:
一个指针从相遇点开始走 
一个指针从链表头开始走 
他们会在环的入口点相遇

证明:
环之前的距离是L 
slow在环中走过的距离为X
环的长度是C
追上相遇的过程中
慢指针走的距离:L+X
快指针走的距离:L+N*C+X(N>=1)
(N为相遇之前fast在环中走的圈数)
慢指针不可能在环中走过超过1圈 
慢指针如果走了一圈 
快指针已经走了两圈了 肯定追上了
快指针走的路程是慢指针的2倍
2(L+X)=L+N*C+X
L+X=N*C
L=N*C-X
L=(N-1)*C+C-X
相遇的节点设为meetNode
(N-1)*C相当于从meetNode走回到meetNode
C-X就是meetNode到相交点的距离
L就是head走到相交点的距离
相当于head和一个从meetNode开始走的
相等的时候就是相交点

思路2:
meetNode下一个作为头list指针
list和head遍历
当两个相交处就为环的入口处
转换成相交问题

相交问题可见:

数据结构与算法 OJ练习第13篇

3°实现

思路1(结论):

struct ListNode* detectCycle(struct ListNode* head) 
{
    struct ListNode* slow = head, * fast = head;
    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast)
        {
            //相遇
            struct ListNode* meet = slow;
            //公式证明
            while (meet != head)
            {
                meet = meet->next;
                head = head->next;
            }
            return meet;
        }
    }
    return NULL;
}

思路2:

//相交函数
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB) 
{
    struct ListNode* tailA = headA;
    struct ListNode* tailB = headB;
    int lenA = 1;
    int lenB = 1;
    while (tailA->next)
    {
        lenA++;
        tailA = tailA->next;
    }
    while (tailB->next)
    {
        lenB++;
        tailB = tailB->next;
    }
    int gap = abs(lenA - lenB);
    struct ListNode* longlist = headA;
    struct ListNode* lesslist = headB;
    if (lenB > lenA)
    {
        longlist = headB;
        lesslist = headA;
    }
    while (gap--)
    {
        longlist = longlist->next;
    }
    while (longlist != lesslist)
    {
        longlist = longlist->next;
        lesslist = lesslist->next;
    }
    if (longlist == lesslist)
        return longlist;
    else
        return NULL;
}

struct ListNode* detectCycle(struct ListNode* head)
{
    struct ListNode* slow = head, * fast = head;
    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast)
        {
            //相遇
            struct ListNode* meet = slow;
            struct ListNode* list = meet->next;
            meet->next = NULL;
            struct ListNode* intersect=getIntersectionNode(head,list);
            return intersect;
        }
    }
    return NULL;
}

4°运行结果

#15环形链表 II#完

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的小恒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值