线性表--环形链表

题目要求:

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 

思路:

由于是环形链表,所以当链表开始循环遍历后,会进入死循环

通过快慢指针的方式解决问题,当快指针进入循环的时候,慢指针还未进入

如果fast指向NULL,则意味着无环

如果带环,当两者都进入环中时,可以理解为初中所学的追击问题,最终快慢两者会相遇

所以是否带环的判断条件就是fast==slow

代码实现:

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include<stdbool.h>
//给你一个链表的头节点 head ,判断链表中是否有环。

//如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。
//为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)
//注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

//如果链表中存在环 ,则返回 true 。 否则,返回 false 。


//通过快慢指针的方式解决问题,追及问题
 struct ListNode 
 {
     int val;
     struct ListNode *next;
 };
 

bool hasCycle(struct ListNode* head) 
{
    struct ListNode* slow = head, * fast = head;
    while (fast&&fast->next!=NULL)
    {
        slow = slow->next;
        fast = fast->next->next;
        if (slow==fast)
        {
            return true;
        }
    }
    return false;
}

拓展思考:

如果fast一次走2步,slow一次走1步,那么两者最终一定能追上,相当于每次fast与slow中的距离缩小1

如果fast一次走3步,slow一次走1步,那么两者不一定能追上,甚至可能会死循环永远追不上

当n为偶数时,最后距离为0,即相遇

当n为奇数时,最后距离为-1,即反超,进入新的追逐,假设环的周长为C,则此时他们之间的距离为C-1

①C-1为偶数,能追上

②C-1为奇数,永远都追不上

在判断了是否相遇后,需要思考如何才能找到链表进环的结点

这里同样使用快慢指针的方式,一个指针从两个相遇的meet处出发,另一个指针从链表的头节点处出发,这两者最终会在进环的结点相遇

slow:L+X                 fast:L+nC+X

所以,L+nC+X=2(L+X)

所以nC-X=L

代码实现:

struct ListNode* detectCycle(struct ListNode* head)
{
    struct ListNode* slow = head, * fast = head;
    while (fast&&fast->next)
    {
        //慢走一步,快走两步
        slow = slow->next;
        fast = fast->next->next;

        if (slow==fast)//当两者在meet位置相遇时
        {
            struct ListNode* meet = slow;
            while (head!=meet)
            {
                head = head->next;//头结点向后推进
                meet = meet->next;//meet在环内循环
            }
            //当while循环结束时,meet==head,即进环位置
            return meet;
        }
    }
    return NULL;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值