文章目录
山川如环,连绵不绝;人生如秀,周而往复。
1. 环形链表
1.1 Leetcode环形链表1
题目:https://leetcode.cn/problems/linked-list-cycle/
分析:
阅读题目,可以知道题目是想要我们判断该链表之中是否含有环,所以我们只需要知道怎么样可以判断是否有环即可。
可以看到普通的链表中有空指针,而带环的链表中没有空指针。所以可以从中出发,初始化一个当指针指向head,依次遍历链表中的各个节点,当为指针指向NULL的时候结束。但是此时带环链表中的指针会陷入循环,所以我们考虑再引入一个指针,用快慢指针
。
快慢指针
指的是设定两个指针,其中快的指针的移动速度是慢的指针的移动速度的两倍。
快慢指针
方法主要用来解决两类问题,即“判断一个链表是否为循环链表”
以及“寻找一个有序链表的中位数”
。
解题:
使用快慢指针,初始化slow和fast都指向head。slow每次向后走一步,fast每次向后走两步,如果fast走到了NULL就说明该链表是普通链表,输出false。
如果为环形链表,则fast一定会比slow先进入环中且不断的循环,等slow也进入环中,两者直接相遇或者fast开始追击slow,因为slow比fast慢一步,所以fast一定会追上slow,当slow==fast成立,输出true。
bool hasCycle(struct ListNode *head) {
struct ListNode*fast;
struct ListNode*slow;
fast=slow=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(fast==slow)
return true;
}
return false;
}
1.2.1 slow走一步,fast走两步,一定会相遇?
由上面的分析可以得到答案是:
一定的
假设链表带环,那么两个指针最后都会进入环,快指针先进环,慢指针后进环。
当慢指针刚进环时,可能就和快指针相遇了,最差情况下两个指针之间的距离刚好就是环的长度。此时,两个指针每移动一次,之间的距离就缩小一步,不会出现每次刚好是套圈的情况。
因此:在满指针走到一圈之前,快指针肯定是可以追上慢指针的,即相遇。
1.2.2 进阶:若slow走一步,fast走n步(n>=3),是否会相遇?
不同与上面,答案:
不一定
和上面的假设一样,这次让快指针走三步,慢指针走一步,两次指针每移动一步,之间的距离就缩小两步。但是和上面不同,如果快指针和慢指针的距离是一的话,快指针就会直接跳过慢指针,造成快慢指针的错过。
所以这里要对fast和slow之间的距离N进行讨论。
如果N为偶数,则可以直接相遇;如果N为奇数,则又需要进入新的一轮追击。
当fast走n步(n>=3)也是一样的步骤。
1.2 Leetcode环形链表2
题目:
https://leetcode.cn/problems/linked-list-cycle-ii/
在这里会有一个结论:
当一个指针从相遇点走,一个指针从起始点走,会在入口点相遇。
有了结论我们就可以很快的找到解题的方法了,我们同样引入快慢指针,先判断是否有环,如果没有环就可以直接返回NULL;
进入环了之后我们开始快慢指针的追击,当快慢指针相遇的时候,我们就使用我们的结论,初始化两个指针分别用来标记相遇点
和链表的起始点
,当一个指针从相遇点走,一个指针从起始点走,会在入口点相遇
,判断它们如果相等的话,那么就说明该相遇点是我们所需要的入口点
。
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode *fast ,*slow;
fast=slow=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(fast==slow)
{
struct ListNode*meet,*start;
meet=fast;
start=head;
while(meet!=start)
{
meet=meet->next;
start=start->next;
}
return meet;
}
}
return NULL;
}
1.2.1 进阶:怎么推出链表中双指针起始点、入口点、相遇点之间的关系?
结论:
一个指针从相遇点走,一个指针从起始点走,会在入口点相遇
L=(n-1)*C+C-X
证明:假设起始点到入口点的距离是L,入口点到相遇点的距离是X,环的距离是C;因为fast比slow每次都快一步,所以fast走的距离是slow的两倍,fast和slow相遇后停止。此时,slow的距离是L+X,fast的距离是L+C+X。由两倍关系可以得:2(L+X)=L+C+X
推出->L=C-X
注意:
这些情况都是L和C差不多长,如果L比C长很多的话,结论就不对了。
在上面的基础上我们将fast指针走的C乘以一个n,即可推出通法L=(n-1)*C+C-X
这些就是有关数据结构中环形链表的简单介绍了😉
如有错误❌望指正,最后祝大家学习进步✊天天开心✨🎉