如何判断单链表中是否有环

有环的定义是,链表的尾节点指向了链接中间的某个节点。比如下图,如果单链表有环,则在遍历时,在通过6之后,会重新回到3,那么我们可以在遍历时使用两个指针,看两个指针是否相等。


此题面试经常见,算法思想是用两个指针p,q,p每次走两步,q每一走一步。如何单链表有环,则p和q相遇;否则p先到达NULL。

有人要问了,为什么单链表有环时p和q就会相遇呢?

假设单链表的长度是n,且带环,那么当走到第i步时,q指向i mod n,p指向2*i mod n.即当 i mod n == 2*i mod n时,p与q相遇。

即(2*i-i) mod n == 0,即i mod n ==0.即i == n.此时p和q第一次相遇.

可以简单理解为p和q同时在操场跑步,其中p的速度是q的两倍,当他们两个同时出发时,q跑一圈到达起点,而p此时也刚好跑完两圈到达起点。

上代码:

int huan()
{
    link p = q = head;
    while(p != NULL && p->next != NULL)        
    {
        p = p->next->next;                   //p每次走两步
        q= q->next;                               //q每次走一步
        if(p == q)
        return 1;
    }
    return 0;
}

条件判断只是为了当链表没环时跳出循环

网上很多解法还判断了q != NULL,其实没必要判断,因为p走的比q快,当q == NULL 时,p其实早就等于NULL了。

条件判断为何还要判断p->next呢?

因为当单链表没环时,每次p的速度是q的2倍,如果p->next == NULL,这时如果继续走,就会出现

p = NULL->next;这是断错误。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值