概述
目录
什么是环?
例题 141. 环形链表
公式推导:
环形链表二 142. 环形链表 II
方法一:
方法二:
什么是环?
类似这种,结点下一个指针又指向链表本身,这样若遍历链表的话则会变成死循环。
特殊情况:自己也有可能成环
环的特点:
有两个指针指向环的起点
判断是否有环
例题 141. 环形链表
使用快慢指针,进入了环就变成了追及相遇的问题
思路:快指针一次走两步,慢指针一次走一步,当两个指针相遇时,即在链表中存在环
问题:为什么是快指针一次走两步?慢指针一次走一步?
bool hasCycle(struct ListNode *head) {
//判断空链表
if(!head){
return NULL;
}
struct ListNode *slow=head;
struct ListNode *fast=head;
//判断条件是什么?
//如果两个指针相等则有一个环
//就把它当作一个正常数组想
//因为只有这样才能从循环中出去
//判断条件怎么想?
while(fast&&fast->next)){
fast=fast->next->next;
slow=slow->next;
//要是环的话根本出不去
if(fast==slow){
return true;
}
}
return false;
}
公式推导:
假设链表中无环
快指针走的距离=2*慢指针走到距离
假设链表中有环
进环前的距离L,环的长度C,环的开始点至相遇点的距离X
慢指针走过的距离:L+X
快指针走过的距离:L+C*N+X
由此可以得出一个等式
L+X=N*C
L=(N-1)*C+C-X
意思是在入环前的长度==环的长度-(开始点至相遇点的距离)
也就是说: 蓝色部分=L
环形链表二
方法一:
本题首先需要找到相遇点,然后设立两个新的指针,两个指针从相遇点和起始点一起走,两个指针相遇的地方即为环形链表的起始点。
struct ListNode *detectCycle(struct ListNode *head) {
//L=C-X
//创立快慢指针
struct ListNode *slow=head;
struct ListNode *fast=head;
//确保fast没有空指针
while(fast&&fast->next){
//两者一起向前走
slow=slow->next;
fast=fast->next->next;
//找到相遇
if(slow==fast){
struct ListNode *meet=slow;
while(meet!=head){
//找到相遇点,两者一起走
meet=meet->next;
head=head->next;
}
//相遇,返回环的起始点
return meet;
}
}
return NULL;
}
方法二:
使用相交链表的方式
先将链表从快慢指针的相遇点处断开
之后新建两个指针分别指向相遇点的下一位和原链表的头
利用相遇链表
相遇点即为起始点
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
//想一想,极端情况
//首先应该判断这两个链表不为空
if(!headA||!headB)
return NULL;
//找到两个链表的最后一个节点
struct ListNode *lastA=headA;
int numA=1;
while(lastA->next)
{
lastA=lastA->next;
numA++;
}
struct ListNode *lastB=headB;
int numB=1;
while(lastB->next)
{
lastB=lastB->next;
numB++;
}
//判断是否相交
//这就是找最后一个节点的作用
if(lastA!=lastB)
{
return NULL;
}
//找到长度,找最长的那个
//不是说不能倒着走吗?难道是要它倒叙?
//理解错了理解错了
struct ListNode *lenglist=headA;
struct ListNode *shortlist=headB;
if(numA<numB)
{
lenglist=headB;
shortlist=headA;
}
//最长的先走
int distance=abs(numA-numB);
while(distance--)
{
lenglist=lenglist->next;
}
//两个一起走
while(lenglist!=shortlist)
{
lenglist=lenglist->next;
shortlist=shortlist->next;
}
//走到不相等时分开,返回相交的节点
return lenglist;
}
struct ListNode *detectCycle(struct ListNode *head) {
//L=C-X
//创立快慢指针
struct ListNode *slow=head;
struct ListNode *fast=head;
//确保fast没有空指针
while(fast&&fast->next){
//两者一起向前走
slow=slow->next;
fast=fast->next->next;
//找到相遇
if(slow==fast){
struct ListNode *meet=slow;
struct ListNode*next=meet->next;
struct ListNode*walk=meet->next;
meet->next=NULL;
struct ListNode *newNode=getIntersectionNode(head,walk);
meet->next=next;
return newNode;
}
}
return NULL;
}
最后
以上就是聪慧路灯为你收集整理的环形链表C/C++数据结构什么是环?例题 141. 环形链表公式推导:环形链表二的全部内容,希望文章能够帮你解决环形链表C/C++数据结构什么是环?例题 141. 环形链表公式推导:环形链表二所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复