链表类题目:找到有环链表的入口结点

题目描述

判断链表是否有环,找到环的入口结点,如果没有环 返回Null

题目解析

  1. 使用set,如果不在set中,那么加入set中,返回第一个已经在set中的节点。

ListNode* LoopEntry(ListNode *head)
{
    if(head == nullptr || head->next==nullptr) return nullptr;

    std::set<ListNode*> st;

    ListNode *cur = head;
    
    while(cur != nullptr)
    {
        //第一次发现set中存在 就返回
        if(st.count(cur))
        {
            return cur;
        }
        st.insert(cur);
        cur = cur->next;
    }
    return nullptr;
}
  1. 使用快慢指针解决:
    在这里插入图片描述

假设快慢指针在棕色部分相遇:此时

slow 的路程长度 = a + b
fast 的路程长度 = a + b + n(b+c), 这里的n指的是快指针可能已经在环中转了n圈了。

由于fast指针的速度是slow指针速度的2倍,那么,相同时间内,路程自然也是slow的二倍了:

2(a + b) = a+(n+1)b + nc,化解以后,a = (n-1)(b+c)+c
如果n1,ac,即,无论n是多少,a和c是相等的
如果n==2, a == b +2c

在这里插入图片描述前面推导出,a == c,当我们的快慢指针相遇后,我们定义一个指针P,每次也是走一步,那么p和slow终会相遇,相遇点就是我们环的入口。

在这里插入图片描述

ListNode* LoopEntry(ListNode*head)
{
    if(head == nullptr || head->next==nullptr)  return nullptr;

    ListNode * slow = head;
    ListNode * fast = head->next;

    while (fast !=nullptr && fast->next != nullptr)
    {
        if(fast == slow)
        {
        	//当确定有环时,定义一个从头开始走的指针,步子大小与slow一致
            ListNode * p = head;
            while(p != slow)
            {
                p=p->next;
                slow = slow->next;
            }
            return p;
        }
        fast = fast->next->next;
        slow = slow->next;
    }
    return nullptr;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值