判断链表是否有环及环的入口

来源:互联网 发布:手机虚拟网络能否上网 编辑:程序博客网 时间:2024/05/16 07:14

1.如何判断是否有环?如果有两个头结点指针,一个走的快,一个走的慢,那么若干步以后,快的指针总会超过慢的指针一圈。

2.如何计算环的长度?第一次相遇(超一圈)时开始计数,第二次相遇时停止计数。

3.如何判断环的入口点:碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。

为什么呢?需要一个简单的计算过程:
(1)当fast与slow相遇时,show肯定没有走完链表,而fast已经在还里走了n(n>= 1)圈。假设slow走了s步,那么fast走了2s步。fast的步数还等于s走的加上环里转的n圈,所以有:
2s = s + nr。因此,s = nr。
(2)设整个链表长为L,入口据相遇点X,起点到入口的距离为a。因为slow指针并没有走完一圈,所以:
a + x = s,带入第一步的结果,有:a + x = nr = (n-1)r + r = (n-1)r + L - a;即:
a = (n-1)r + L -a -x;
这说明:从头结点到入口的距离,等于转了(n-1)圈以后,相遇点到入口的距离。因此,我们可以在链表头、相遇点各设一个指针,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。
也许大家有一个问题,就是为什么“当fast与slow相遇时,show肯定没有走完链表”。这个问题比较坑,我也没有找到很好的证明。不过大家自己画几个试试,会发现的确是这样。

4.如何判断两个链表(不带环)是否相交?将其中的一个链表首尾相连,然后判断另一个链表是否带环即可。这个比较简单,程序就省略了。

#include <stdio.h>typedef struct ListNode{    int val;    ListNode *next;}ListNode,*pNode;//判断是否有环bool isLoop(ListNode *pHead){    ListNode *slow = pHead;    ListNode *fast= slow->next;    //如果无环,则fast先走到终点    //当链表长度为奇数时,fast->Next为空    //当链表长度为偶数时,fast为空    while( fast != NULL && slow != NULL)    {        fast = fast->next;        slow = slow->next;        //如果有环,则fast会超过slow一圈        if(fast == slow)        {            break;        }    }    if(fast == NULL || slow== NULL  )        return false;    else        return true;}//计算环的长度int loopLength(ListNode *pHead){    if(isLoop(pHead) == false)        return 0;    ListNode *slow = pHead;    ListNode *fast = slow->fast;    int length = 0;    bool begin = false;    bool agian = false;    while( fast != NULL && fast->next != NULL)    {        fast = fast->next;        slow = slow->next;        //超两圈后停止计数,挑出循环        if(fast == slow && agian == true)            break;        //超一圈后开始计数        if(fast == slow && agian == false)        {                       begin = true;            agian = true;        }        //计数        if(begin == true)            ++length;    }    return length;}//求出环的入口点Node* findLoopEntrance(ListNode *pHead){    ListNode *slow = pHead;    ListNode *fast = slow->fast;    while( fast != NULL && slow!= NULL)    {        fast = fast->next;        slow = slow->next;        //如果有环,则fast会超过slow一圈        if(fast == slow)        {            break;        }    }    if(fast == NULL || slow == NULL)        return NULL;    slow = pHead;    while(slow != fast)    {        slow = slow->next;        fast = fast->next;    }    return slow;}
阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小牛u1钥匙丢了怎么办 非牛顿流体干了怎么办 刺激战场0信誉分怎么办 假如非牛顿干了怎么办? 退出id后照片了怎么办 小麦收割机麦糠有籽粒怎么办 在家带娃没钱花怎么办 看3d电影近视的怎么办 摩托车电瓶没电了怎么办 踏板摩托车电瓶没电了怎么办 摩托车离合油没了怎么办 论文数据计算错误该怎么办 脚被擦破皮了痛怎么办 脚撞到了很疼怎么办 腿不小心磕青了怎么办 木制椅子腿断了怎么办 实木椅子腿断了怎么办 铁质椅子腿断了怎么办 大套摩托车查车怎么办 摩托车本扣12分怎么办 蓝牙耳机上面的软套掉了怎么办 工作不想干了怎么办啊 浴室门玻璃坏了怎么办 电梯顶层安全安全距离不合格怎么办 制冰机有些孔不出水怎么办 制冰机排水孔堵住了怎么办 点我达装备抽查怎么办 空军常服大檐帽有一点变形怎么办 一般纳税人没有进项发票怎么办 汽车购买发票丢了怎么办 购买房子的发票丢了怎么办 购买的二手房发票丢失怎么办 购买空调时的发票丢失怎么办 发票购票本丢了怎么办 留学中介费贵了怎么办 车祸伤者不肯出院怎么办 增值税普通发票发票联丢失怎么办 纳税识别号错了怎么办 电子发票税号填写错误怎么办 发票抬头名称写错了怎么办 滴滴发票抬头写错了怎么办