博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
判断单链表是否存在环及寻找环的入口点
阅读量:5115 次
发布时间:2019-06-13

本文共 1980 字,大约阅读时间需要 6 分钟。

判断一个单链表是否存在环的解法如下:

1.遍历链表,将链表的节点存入hash表内,若遍历到后面的节点已存在hash表内,说明有环。时间:O(n) 空间:O(n)

2.反转链表,时间:O(n) 空间:O(1),使用3个指针:pNext、pPrev、pCur。这种方法有副作用,就是若存在环的话,无法还原到链表原始状态。(弃用)

3.快慢指针法,时间:O(n) 空间:O(1)。

问题1:快慢指针何时相遇,是否回转几十圈,才相遇呢?

证明1:设环长为L,slow指针第一次进入环内,fast指针在前方的a节点处(0<a<L),经过x次移动后两个指针相遇。那么即有:

0+x = (a+2x)(mod L) => 0= a+x(mod L) 两边同时减去x

就是说a+x对L求余应该是0,即a+x=0,L,2L……这一系列的解取最小的那个。

得出x=L-a,就是说slow指针进入环后向前移动L-a个位,fast指针向前移动了2L-2a个位,如下图所示:

问题2:如何求前面的子链长度呢?(即环入口点)

证明2:假设在fast与slow第一次相遇是,slow总共走了n步,fast走了2n步。

slow的路径为:n=p+x,x为相遇点到环入口的距离。

fast的路径为:2n=p+x+k*L

可以看出slow到达相遇点后再走n步,还是回到相遇点(p+x)。

将fast置到起点,步长为1,经过n步,也会到达相遇点。这个过程中只有前p步的路径不同,所以当slow与fast再次重合是必然在环入口点上。

下面附上代码:

#include 
using namespace std;struct node{ int value; node* next; node(node *p=NULL) { value=0; next=p; } node(const int v,node *p=NULL) { value=v; next=p; }};node* detectLinkListLoop(node *first){ node *fast,*slow; fast=slow=first; while(fast && fast->next) { slow=slow->next; fast=fast->next->next; if (fast == slow) break; } return !(fast == NULL || fast->next == NULL);}node* FindLoopPort(node *head){ node *slow = head, *fast = head; while ( fast && fast->next ) { slow = slow->next; fast = fast->next->next; if ( slow == fast ) break; } if (fast == NULL || fast->next == NULL) return NULL; slow = head; while (slow != fast) { slow = slow->next; fast = fast->next; } return slow;}void main(){ node* A=new node(1); node* B=new node(2); node* C=new node(3); node* D=new node(4); node* E=new node(5); node* F=new node(6); node* G=new node(7); node* H=new node(8); A->next=B; B->next=C; C->next=D; D->next=E; E->next=F; F->next=G; G->next=H; H->next=C; node* first=A; cout<
<

感谢两位gocalf、xudacheng06博主的指导,参考文章:

转载于:https://www.cnblogs.com/Linkabox/p/3355232.html

你可能感兴趣的文章
hihoCoder #1831 : 80 Days-RMQ (ACM/ICPC 2018亚洲区预选赛北京赛站网络赛)
查看>>
图片等比例缩放及图片上下剧中
查看>>
WebView加载网页详情
查看>>
【转载】Linux screen 命令详解
查看>>
dd命令 建立两颗一模一样的磁盘
查看>>
常用的jquery触屏手机页面特效代码下载
查看>>
background-clip,background-origin
查看>>
C# 如何创建一个Windows服务
查看>>
集群和分布式区别
查看>>
Android(java)学习笔记153:采用post请求提交数据到服务器(qq登录案例)
查看>>
Java基础知识强化101:Java 中的 String对象真的不可变吗 ?
查看>>
Android 高级UI设计笔记12:ImageSwitcher图片切换器
查看>>
虚拟主机与虚拟目录学习小结
查看>>
hlg1414安装雷达【贪心】
查看>>
Blog文章待看
查看>>
Golang flag包使用详解(一)
查看>>
python文件IO
查看>>
升级到 .NET Core 2.1
查看>>
对Java前四章的感受
查看>>
【Linux】ping命令详解
查看>>