链表OJ9——环形链表1

声明:我的链表OJ系列是针对无头单向不循环链表的

题目

题目:. - 力扣(LeetCode)

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

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

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

思路

快慢指针是一种常用的技巧,用于检测链表中是否存在环。

这种方法的原理基于两个指针以不同的速度遍历链表:一个指针每次移动一步(称为慢指针或乌龟),另一个指针每次移动两步(称为快指针或兔子)。

如果链表中存在环,那么快指针最终会追上慢指针,两个指针会在环内的某个节点相遇。如果链表中没有环,那么快指针将会先到达链表的尾部(即NULL),此时就可以判断链表没有环。

下面是这个思路的详细步骤:

  1. 初始化快慢指针
    • 慢指针(乌龟)指向链表的头节点。
    • 快指针(兔子)也指向链表的头节点,但比慢指针先走一步,即指向头节点的下一个节点。
  2. 开始遍历
    • 慢指针每次向前移动一个节点。
    • 快指针每次向前移动两个节点。
  3. 检查相遇情况
    • 在每次移动后,检查快慢指针是否相遇(即指向同一个节点)。
    • 如果相遇,说明链表中存在环。
    • 如果快指针到达链表的末尾(即NULL),说明链表中没有环,因为快指针的速度是慢指针的两倍,如果快指针已经遍历完整个链表,慢指针最多只遍历了链表的一半,而链表仍然未结束,说明存在环之外的部分。
  4. 返回结果
    • 如果快慢指针相遇,返回true表示链表有环。
    • 如果快指针到达链表末尾,返回false表示链表无环。

这个方法的时间复杂度是O(n),其中n是链表的长度,因为快指针最多遍历整个链表一次。空间复杂度是O(1),因为我们只使用了两个指针变量。

代码实现 

bool hasCycle(struct ListNode* head) {  
    // 如果链表为空或者只有一个节点,那么肯定没有环  
    if (head == NULL || head->next == NULL) {  
        return false;  
    }  
  
    // 使用快慢指针来检测链表是否有环  
    // 慢指针每次移动一步,快指针每次移动两步  
    struct ListNode* slow = head;     // 慢指针,每次移动一步  
    struct ListNode* fast = head->next; // 快指针,初始时指向第二个节点,每次移动两步  
  
    // 当快慢指针不相遇时,继续循环  
    while (slow != fast) {  
        // 如果快指针已经到达链表末尾(或者快指针的下一个节点到达链表末尾),说明链表没有环  
        if (fast == NULL || fast->next == NULL) {  
            return false;  
        }  
  
        // 慢指针移动一步  
        slow = slow->next;  
  
        // 快指针移动两步  
        fast = fast->next->next;  
    }  
  
    // 如果快慢指针相遇,说明链表有环  
    return true;  
}

这段代码使用了快慢指针的方法来检测一个链表中是否有环。快指针每次移动两步,慢指针每次移动一步。如果链表中存在环,那么快慢指针最终会在环内的某个节点相遇;如果链表中没有环,那么快指针会先到达链表的末尾(即fast == NULLfast->next == NULL),这时就可以判断链表没有环。

这种方法的时间复杂度是O(n),其中n是链表的长度。在最坏的情况下,即链表恰好形成一个环时,快指针会在遍历链表的一半长度时与慢指针相遇。空间复杂度是O(1),因为只使用了两个指针变量。

拓展

为什么快指针每次走两步,慢指针走一步可以?

假设链表带环,两个指针最后都会进入环,快指针先进环,慢指针后进环。

当慢指针刚进环时,可 能就和快指针相遇了,最差情况下两个指针之间的距离刚好就是环的长度。

此时,两个指针每移动 一次,之间的距离就缩小一步,不会出现每次刚好是套圈的情况,因此:在满指针走到一圈之前, 快指针肯定是可以追上慢指针的,即相遇。

快指针一次走3步,走4步,...n步行吗?

我们可以假设:快指针每走三步,慢指针每次走一步,此时快指针肯定先进环,慢指针后来才进环。

假设慢指针进环时,快指针的位置如图所示:

此时按照上述方法来绕环移动,每次快指针走3步,慢指针走1步,是永远不会相遇的,快指针刚好将慢指针套圈了,因此不行。

只有快指针走2步,慢指针走一步才可以,因为换的最小长度是1,即使套圈了两个也在相同的位置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值