力扣第141题和142题-环形链表,是否有环,环的入口节点

因这2道题均不改变链表结构,所以可以不创建新的临时头结点

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head) {
    if(head==NULL||head->next==NULL)//若只有一个数据结点指向自己head->next!=NULL:head->next!=NULL
    return false;
    struct ListNode*p1=head->next;//一次走一步
    struct ListNode*p2=head->next->next;//一次走两步
    while(p2!=NULL&&p2->next!=NULL)
    {
        if(p1==p2)
        return true;
        p1=p1->next;//不等接着走
        p2=p2->next->next;//p2->next!=NULL

    }//为空无环
    return false;
}

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) {
    //1.处理判断环
    if(head==NULL||head->next==NULL)//没有环;若只有一个数据结点指向自己head->next!=NULL:head->next!=NULL
    return false;
    //定义快慢2个指针
    struct ListNode*p1=head->next;//一次走一步
    struct ListNode*p2=head->next->next;//一次走两步
    while(p2!=NULL&&p2->next!=NULL)
    {
        if(p1==p2)//相遇则有环,此时p2一定比p1多走一圈(类似于操场跑圈),即环的长度n;且p2=2*p1
        //2(x+y)=x+y+n——>x=n-y;或者2(x+y)=x+y+dn——>x=dn-y=n-y+(d-1)n;2者最终化简结果一样
        //x为头结点到入口结点的距离,y为入口结点到相遇结点的距离;所以x+y为从头结点到相遇结点的距离==环的一圈的距离,x+y=n
        //慢指针p1走了x+y的距离,快指针比慢指针多走一圈(或者是多走d圈),即p2=x+y+n
        //因为p2=2*p1,所以2(x+y)=x+y+n;则x+y=n

       break;
        p1=p1->next;//不等接着走
        p2=p2->next->next;//p2->next!=NULL

    }//为空无环
    if(p2==NULL||p2->next==NULL)//没有环
    return NULL;
    //2.计算环的长度
    int n=1;//n为环的长度
    p1=p1->next;//p1从头开始,走到x+y处即一个n
    while(p1!=p2)//p2还在之前相遇的结点处,x+y处
    {
        n++;
        p1=p1->next;
    }
    //3.入口处的结点距离为x,现在求x
    p1=head;//先走的指针
    p2=head;//后走的指针
    while(n>0)//让p1先走n步,即p1先走一圈,走到x+y处,则n-y=x,即p1再走x步就到入口处x
    {
        p1=p1->next;
        n--;
    }//此时p1==x+y,p2==head;2者均再走x步同时到达x处相遇

    while(p1!=p2)//现在p1,p2同时走,均一次一步;再次相遇时就是入口处,即p1==p2
    {
        p1=p1->next;
        p2=p2->next;
    }
    return p1;//相遇的点就是入环点


}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值