[C语言]环形链表题解

目录

一.环形链表Ⅰ

1.题目描述

2.题解

(1)快慢指针

(2)拓展

 ①为什么一定会相遇?

②slow走1步,fast走3步 n步呢?

 二.环形链表Ⅱ

1.题目描述

2.题解

(1) 快慢指针


一.环形链表Ⅰ

1.题目描述

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

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

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

提示:

  • 链表中节点的数目范围是 [0, 104]
  • -105 <= Node.val <= 105
  • pos 为 -1 或者链表中的一个 有效索引 。

2.题解

(1)快慢指针

思路及算法:具体地,我们定义两个指针,一快一慢。慢指针每次只移动一步,而快指针每次移动两步。初始时,快慢指针都在位置 head,这样一来,如果在移动的过程中,快指针反过来追上慢指针,就说明该链表为环形链表。如果链表中没有环,那么快指针会先到达链表尾部(null)。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head) {
    struct ListNode *slow=head;
    struct ListNode *fast=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
        {
            return true;
        }
    }
    return false;
}

复杂度分析

  • 时间复杂度:O(N),其中 N 是链表中的节点数。

    • 当链表中不存在环时,快指针将先于慢指针到达链表尾部,链表中每个节点至多被访问两次。

    • 当链表中存在环时,每一轮移动后,快慢指针的距离将减小一。而初始距离为环的长度,因此至多移动 N 轮。

  • 空间复杂度:O(1),我们只使用了两个指针的额外空间。

 链接在这里哦,看完可以自己试一试:141. 环形链表 - 力扣(LeetCode) 

(2)拓展

 ①为什么一定会相遇?

②slow走1步,fast走3步 n步呢?

(以下只讲解3步的情况,n步问题就留给大家吧~)

slow 走距离是: L         fast 走的距离: L + x * C + C - N 
 (slow 进环时,假设 fast 已经在环里面转了 x 圈)(fast 走的距离是 slow 的3倍)

 3* L = L + x * C + C - N 

=>2* L =( x +1)* C - N 
如果同时存在 N 是奇数且 C 是偶数,那么就永远追不上
偶数=( x +1)*偶数﹣奇数
只有奇数﹣奇数才能等于偶数,但是( x +1)*偶数一定是偶数
所以反证出 N 是奇数且 C 的偶数不能同时存在,永远追不上的条件不成立
结论:一定能追上
 N 是偶数第一轮就追上了
 N 是奇数第一轮追不上, C-1是偶数第二轮就追上

 二.环形链表Ⅱ

1.题目描述

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

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

不允许修改 链表。

提示:

  • 链表中节点的数目范围在范围 [0, 10^4] 内
  • -10^5 <= Node.val <= 10^5

2.题解

(1) 快慢指针

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* detectCycle(struct ListNode* head) {
    struct ListNode *slow = head, *fast = head;
    while (fast != NULL&&fast->next!=NULL) {
        slow = slow->next;
        fast = fast->next->next;
        if (fast == slow) {
            struct ListNode* meet = slow;
            while (head != slow) {
                head= head->next;
                meet = meet->next;
            }
            return ptr;
        }
    }
    return NULL;
}

当head走过L到入环节点,slow走了(x-1)*C+C-N到入环节点

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值