数据结构-链表里面的环

目录

1、什么是环:

 2、如何判断链表是否含有环

   方法1(最优解):快慢指针:

        方法2:取极限思维(一般情况可取)

                方法3:哈希表(不是很推荐)

3、求环的入口

1、什么是环:

        环:是链表里面出现指向自己或者指向这个结点前面的元素,从而使链表形成一个闭环的状态。

 2、如何判断链表是否含有环

   方法1(最优解):快慢指针:

      思路:设置两个指针p、q,开始都在头结点,但是p走一步,q走两步。这样子,如果是没有环的链表,p,q是不可能相遇的

但是如果链表里面含有环,则他们一定会相遇 

代码实现: 

bool hasCycle(struct ListNode* head ) //bool函数,返回true或者false
{
    if(head == NULL )//代码为空,直接返回
    {
         
        return false;
    }
    struct ListNode*p = head;
    struct ListNode*q = head;
     
    while(p != NULL && p->next !=NULL)//注意遍历的条件,避免段错误
    {
        p = p->next->next;
        q = q->next;
        if(q == p)//如果相遇则有环
        {
            return true;
        }
    }
    return false;//没有相遇
}

方法2:取极限思维(一般情况可取)

        思路:用一个指针去遍历链表,同时设置一个计数器,每遍历一个元素则加一次,如果当计数器到达一个非常大的数字,则一般可以判断这个链表含有环。

代码实现:

bool hasCycle(struct ListNode* head ) {
    if(head == NULL )
    {
         
        return false;
    }
    struct ListNode*p = head;
    int cut = 0 ;
    while(p)
    {
       cut++;
       p = p->next;
       if(cut == 100000000)
       {
            return true;
       }
    }
    return false;
}

方法3:哈希表(不是很推荐)

        思路:每次记录遍历的结点的数,进行比较有没有回到这个结点,但是如果有相同的元素,则不好判断。

3、求环的入口

        有了上面的知识,现在我们可以考虑一个新的问题,将环的入口求出来如上图,环的入口为3,那么我们怎么通过代码求出来呢?

        思路:同样,我们需要判断该链表是否为带环链表,使用快慢指针的方法。当两个指针相遇,即证明有环,此时:将p返回头节点,q留在相遇的结点,p,q再分别一步一步的进行遍历,当p,q再次相遇,则该节点必定为环的入口。

代码实现:

struct ListNode* EntryNodeOfLoop(struct ListNode* pHead ) 
{
    struct ListNode*p = pHead;
    struct ListNode*q = pHead;
    if(pHead == NULL)
    {
        return NULL;
    }
    while(p != NULL&&p->next!=NULL)
    {
        p = p->next->next;
        q = q->next;
        if(q == p)//有环
        {
            p = pHead;
            while(q != p )//以相遇为条件进行循环遍历
            {
                p = p->next;
                q = q->next;
            }
            return p;
        }
    }
    return NULL;
}

  • 8
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

&菜团子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值