判断两个单向链表是否存在环

今天Mayuyu来带领你们讨论如下三个问题:

 

 (1)如何判断一个单链表是否存在环 ?

 (2)如果存在环,如何找到环的入口点?

 (3)两个链表中有环时,如何判断相交?

 

 

问题一

 

我们设置两个指针,分别是fast和slow,初始都指向这个单向链表的表头,fast每次走两步,而slow每次走一步,

所以,我们知道如果有环,那么fast先进入环,slow后进入环,在经过若干次这样的步骤,必定会有fast与slow

相遇,那么我们就能判断是否存在环了。如果不存在环,则fast先走到链表尾。

 

所以我们很容易得到如下代码:

bool isLoop(list *head)
{
    list *slow = head;
    list *fast = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast) return true;
    }
    return false;
}


 

 

问题二

 

上面问题一我们已经能判断一个单向的链表是否存在环,如果一个单向链表存在环,我们如何求它的环入口点?

 

如下图

 

首先,我们设head到入口点的距离为,入口点到相遇点的距离为,沿着相遇点继续走到入口点的距离为

链表总长度为,fast指针与slow指针相遇时slow一共走了步,那么很明显fast就走了步,相遇时fast比

slow多走了圈。

 

所以我们很容易得到,即

 

又由于,所以,得到:

 

这个表达式说明从相遇点到入口点的距离与head到入口点的距离取余后是相等的。所以我们可以在相遇点和head处

各设置一个指针,然后同时走,它们会在入口处相遇,这样我们也就能找到这个入口了。

 

代码如下:

 

list *FindPort(list *head)
{
    list *slow = head;
    list *fast = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast) break;
    }
    if(fast == NULL || fast-next == NULL)
        return NULL;
    slow = head;
    while(slow != fast)
    {
        slow = slow->next;
        fast = fast->next;
    }
    return slow;
}


 

 

问题三

 

实际上,我们先要明确一个事实,那就是如果一个单链表有环,另一个单链表没有环,那么这两个单链表一定不会

相交。这是单链表的next指向的唯一性决定的,一个节点不可能有两个或者多个后继分支。

 

所以,如果是两个有环链表相交,那么它们一定存在一个公共的环,大致如下两个图形:

 

                                                                  

 

 

所以,明确了以上事实之后,我们可以这样来做:

 

先分别求出这两个有环链表的环的入口点,如果入口点相等,那么说明这两个有环链表就相交了。如果不相等,就有

两种情况:

 

    (1)两个有环链表不相交

    (2)它们相交但环入口点不同

 

那么我们如何判断,这个就比较简单了。

 

我们设一个环的入口点为port,在另一个环的入口点设置一个指针p往后走,如果一周内出现p->next == port,

那么说明这两个有环链表共环,也就是说相交,否则这两个有环链表不相交。

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值