快慢指针法:链表判环与入环节点查找

给定一个链表,如何判断它是否有环?

最直观的思路是:如果能一路走到 NULL,说明没有环。
但为了更高效,我们使用 快慢指针 来解决。

判环思路

  • 建立快指针 fast 与慢指针 slow

  • 每次循环:slow 走一步,fast 走两步。

  • 如果过程中出现 fast == slow,则说明链表存在环。

  • 如果 fastfast->nextfast->next->next 为空,则链表无环。

    struct ListNode * fast =head;
    struct ListNode * slow =head;
    while(fast&&fast->next&&fast->next->next)
    {   
        slow=slow->next;
        fast=fast->next->next;
        if(fast==slow)
        return true;
    }
    return false;

🔹 入环节点查找

当我们确定链表有环后,还可以进一步找出 入环的节点

这个问题可以转化为 两个链表相交点 的问题:

  • 相遇点记为 meet = fast->next

  • meet->next 暂时断开,这样链表就被分成了两条;

  • 分别计算两条链表的长度差,长的先走差值步;

  • 然后两条链表同步前进,第一次相遇的节点就是 入环节点

struct ListNode * fast = head;
    struct ListNode * slow = head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
        break;
    }
    struct ListNode * meet = fast;
    while(meet&&meet->next)
    {
        struct ListNode * newhead = meet->next;
        meet->next=NULL;
        while(1)
        {
            struct ListNode * new1 =  newhead;
            struct ListNode * new2 =  head;
            int count1=0;
            int count2=0;

            while(new1)
            {
                new1=new1->next;
                count1++;
            }
            while(new2)
            {
                new2=new2->next;
                count2++;
            }
            struct ListNode * newfast =  newhead;
            struct ListNode * newslow =  head;
            int c= count1-count2;
            if(count1<count2)
            {
                newfast = head;
                newslow=newhead;
                c=count2-count1;
            }
            while(c--)
            {
                newfast=newfast->next;
            }
            while(newfast!=newslow)
            {
                newfast=newfast->next;
                newslow=newslow->next;
            }
            meet->next=newhead;
            return newfast;
        }

    }
    return NULL;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值