判断链表有环及其扩展问题
来源:互联网 发布:爱知日语培训学校 编辑:程序博客网 时间:2024/05/15 13:19
判断链表有环及其扩展问题
单链表里可能有环,如何判断有环?
环大小是多少?能否找到环的第一个节点?
(1)判断有环
设置两个指针,快慢指针,p1,p2,p2一次走两步,p1一次走一步。如果p2走的过程中到达表尾,则没有环,否则p1,p2回进入环,p2会追上p1。此时有环。扩展1
2个指针走的步数可以扩展吗?比如p1走2步,p2走3步等等。再后面我来谈论这个问题。
注意:
1. p1,p2同起点。我在面试中,让p2先走了一步,导致后面的分析“跑偏了”。悲剧。
bool HasACircle(LinkNode *l){ if(NULL == l) return false; LinkNode *p1, *p2; p1 = p2 = l; do { if(NULL != p2 && NULL != p2->next) { p2 = p2->next->next; p1 = p1->next; } else return false; }while(p1 != p2); return true;}
(2)环大小是多少
因为找到了相遇点,链表里有环。那么在相遇点开始,进行遍历并且计数,再次遇到这个点时,计数的数就是环的大小。///在(1)的基础上,添加int CircleNumInLink(LinkNode *l){ if(NULL == l) return 0; LinkNode *p1, *p2; p1 = p2 = l; do { if(NULL != p2 && NULL != p2->next) { p2 = p2->next->next; p1 = p1->next; } else /// 没有环,在这里返回。 return 0; }while(p1 != p2); /// 如果执行到这里,则说明有环,p1,p2指向相遇点 int cnt = 0; do { ++cnt; p2 = p2->next; }while(p1 != p2); return cnt;}
(3)能否找到环的第一个节点
在走1,2步的前提下。如果有环,慢指针肯定能走到环的第一个节点。
假设此时走了 k 步,环第一个节点为起始点,环大小为 N。
那么快指针走了 2k 步,领先慢指针 k 步,相当于落后慢指针 (N-k)步。
每走一次,快指针都会追上 (2 - 1)步,那么再进行 (N-k)次,快的就能追上慢的。此时慢指针又走了 (N-k)步,在环里的位置是 (N-k)。而且这里是相遇点。和起始点的位置差是 k。
而从链表头开始,到达环的起始点距离也是 k。
那么就可以从头和相遇点开始分别遍历,如果相遇,则到达环的起始点。
如下图,
上面的推导可以得出,
快慢指针步数为 1, 2时,
相遇时,慢指针最多走了一圈。
///在(1)的基础上,添加LinkNode * CircleNumInLink(LinkNode *l){ if(NULL == l) return NULL; LinkNode *p1, *p2; p1 = p2 = l; do { if(NULL != p2 && NULL != p2->next) { p2 = p2->next->next; p1 = p1->next; } else /// 没有环,在这里返回。 return NULL; }while(p1 != p2); /// 如果执行到这里,则说明有环,p1,p2指向相遇点 p1 = l; while(p1 != p2) { p1 = p1->next; p2 = p2->next; } return p1;}
扩展1.
按照(3)的思路,但是如果慢指针走的步数不是 1 的话,那么它可能第一次进环的时候不在环的起始点。不过没关系,在这里,只讨论步数扩展能否相遇的问题。进环后,就考虑步数差和相对位置,
问题转化为,慢的走0步, 快的走 步数差 步。
看看快的能否在整数次行走之后,到达慢的位置。
假设 快慢指针的步数差为 w。
慢指针第一次进环时,走了 x 次。
环的大小为 N 。
按照上面的转化,此时设慢节点的位置为起始点。
慢指针都 0 步,快指针走 w步。
看看快指针能否在整数次行走之后,到达起始点。
再走 y 次,相遇。
如果对于任意的 w, x, N。都有一个 y 的整数解,
那么步数可以随意扩展,当然步数差不能是0了。
否则,不能任意扩展。
那么
在环里,快指针领先了 wx 步,相对位置 领先了 (wx) % N 。
如果存在,正整数(包括0) y,z
使得
y × w + (wx) % N = z × N。(1)
则可以随意扩展。
其中
wx % N = wx + z1 × N, z1是整数且 z1 <=0。
带入(1)
y × w + x × w + z1 × N = z × N
==>
y × w + x × w = (z-z1) × N
==>
(x + y) × w = (z-z1) × N
即 (x + y) × w 是 N 的整数倍
显然会存在整数y,
所以可以随意扩展。
感谢网络上的博客们,很多都是参考他们的想法。由于看的很多,就不一一贴出博客地址了。
再次感谢。
0 0
- 判断链表有环及其扩展问题
- 单链表判断是否含有环及其扩展问题
- 判断链表中是否存在环问题、判断两个链表是否相交问题及其扩展
- 字符串回文问题及其扩展
- 【原创】九九乘法表问题及其扩展
- 八数码问题及其扩展
- 字符串的排列组合及其扩展问题
- 扩展欧几里得及其扩展
- 求最大子数组之和及其一些扩展问题
- hdu4021——N数码问题及其扩展
- 判断一个单链表是否有环及其衍生问题
- ACEGI标签及其扩展
- 欧几里得算法及其扩展
- 巴科斯范式及其扩展
- 折半查找及其扩展
- 欧几里德及其扩展
- 二分搜索及其扩展
- 最小二乘法及其扩展
- yii2学习笔记(一)
- 读中文文件,防止乱码(用字符流)
- Android开发_传感器
- Windows系统内存计数器理解解析
- C语言main函数的三种形式
- 判断链表有环及其扩展问题
- Android Studio 1.1.0 无法在ActionBar显示模糊进度条Indeterminate ProgressBar
- ACCESS2010 如何批量自动运行“已保存的导入”或“已保存的导出”
- 物联网1122班刘佳作业
- 数据结构算法集---C++语言实现
- Android 基础概述(二)
- oracle查看表空间使用情况
- C#调用C++封装(续)
- python 爬虫(2)异常的处理和HTTP状态码的分类