
❄专栏传送门:《C语言》、《数据结构与算法》、C语言刷题12天IO强训、LeetCode代码强化刷题
🍉学习方向:C/C++方向
⭐️人生格言:为天地立心,为生民立命,为往圣继绝学,为万世开太平

**前言:**牛客网和LeetCode的刷题都不可或缺,我们都要做一做,无论是参加竞赛还是笔试面试,至少能提升你的代码能力!洛谷的题目也可以去做一做。力扣的题目对提升代码能力很有帮助,需要有一点基础,几乎都是接口型的题目,关于接口型和IO型的区别我们在本专栏的第一篇【LeetCode】力扣题------轮转数组、消失的数字、数组串联中就介绍过了,这里不再赘述,我们进入今天的力扣题目介绍------
目录
[二、环形链表 II](#二、环形链表 II)
正文
本文博主选择了力扣的两道【环形链表】的题目。
通过算法题的训练,我们就把【环形链表】给过了一遍。
一、环形链表
博主题解链接:快慢指针解决环形链表问题
推荐大家可以直接去看博主在力扣上面写的题解,博主介绍的还是比较详细的。
题目描述:


题目还有这个要求------

1、思路
我们的思路是:快慢指针,慢指针每次走一步,快指针每次走两步,如果slow和fast指向同一个节点,说明链表带环。
2、解题过程
像这种题目拿到手我们首先就是想到要画图,一定要有这个意识,数据结构的算法题一定要画图。
如下图所示------

3、代码演示
接下来我们实现一下这个程序------
代码演示:
cpp
//fast每次走两步
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode ListNode;
bool hasCycle(struct ListNode *head)
{
//创建快慢指针
ListNode* fast = head;
ListNode* slow = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
{
//相遇
return true;
}
}
//链表不带环
return false;
}
如果fast每次走三步,我们要特殊处理一下------
cpp
int n = 3; //fast每次走三步,特殊处理一下
while (n--)
{
if (fast->next)
fast = fast->next;
else
return false;
}
代码演示:
cpp
//fast每次走3步
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode ListNode;
bool hasCycle(struct ListNode* head)
{
//创建快慢指针
ListNode* fast = head;
ListNode* slow = head;
while (fast && fast->next)
{
slow = slow->next;
int n = 3; //fast每次走三步,特殊处理一下
while (n--)
{
if (fast->next)
fast = fast->next;
else
return false;
}
if (slow == fast)
{
//相遇
return true;
}
}
//链表不带环
return false;
}
复杂度:时间复杂度:O(N),空间复杂度:O(1)。
4、证明环形链表相遇问题



所以,不管fast每次走几步,一定会相遇。
5、其他思路
我们也可以创建数组:

二、环形链表 II
博主题解链接:找尾节点解决环形链表问题
推荐大家可以直接去看博主在力扣上面写的题解,主包介绍的还是比较详细的。
题目描述:


同样, 这道题目也有这个要求------

这道题LeetCode标注的是【中等】难度,但这个中等难度指的是思路不好想而不是代码不好写。
1、思路
我们的思路:快慢指针,在环里一定会相遇,相遇点到入环节点距离 == 头节点到入环节点距离。
2、解题过程
像这种题目拿到手我们首先就是想到要画图,一定要有这个意识,数据结构的算法题一定要画图。
如下图所示------

3、代码演示:
cpp
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode ListNode;
struct ListNode *detectCycle(struct ListNode *head)
{
//创建快慢指针
ListNode* slow = head;
ListNode* fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
{
//相遇点---------找入环节点(相遇点到入环节点距离 == 头节点到入环节点距离)
ListNode* pcur = head;
while(pcur != slow)
{
pcur = pcur->next;
slow = slow->next;
}
return pcur;
}
}
//链表不带环
return NULL;
}
复杂度:时间复杂度:O(N),空间复杂度:O(1)。
4、证明

结尾
往期回顾:
【LeetCode&数据结构】单链表的应用------随机链表的复制问题、相交链表问题详解
【牛客&LeetCode&数据结构】单链表的应用------移除链表元素问题、链表分割问题详解
【牛客&LeetCode&数据结构】单链表的应用------合并两个有序链表问题、链表的回文结构问题详解
【LeetCode&数据结构】单链表的应用------反转链表问题、链表的中间节点问题详解
【LeetCode】用双指针解决移除元素问题、合并两个有序数组求解
【LeetCode】力扣题------轮转数组、消失的数字、数组串联
**结语:**本篇文章到这里就结束了,本文讲述的两道代码题并不适合C语言初学者,需要有一定的C语言基础,最好要学过数据结构与算法的算法复杂度和链表的知识,才能写出复杂度较优的代码来。大家一定要自己动手敲一敲,不敲的话不仅容易忘记,也不方便将来复习。