数据结构与算法分析笔记与总结(java实现)--链表7:含环链表找环入口结点问题
来源:互联网 发布:painter是什么软件 编辑:程序博客网 时间:2024/05/18 09:19
思路:对于单链表,如果有环,那么环只能在链表的结尾。即总是可以看做在链表的尾结点有一个指向中间某个结点的指针。关键是如何找到这个环的入口,要探索出环入口的特征。
利用一个性质:假设环的结点数目为n,指针从头结点开始p1比p2先走n步,然后一起向下走,当两个指针发生重合时的位置就是环的入口结点。
于是需要先判断链表是否有环,环中结点的数目n,然后就可以找到入口结点。
如何判断链表是否有环?
使用两个指针p1,p2,速度分别为1,2,同时向下移动,当某时刻两个指针相同时说明有环,且这个重合点在环的内部,然后对于速度为1的指针p1记录位置,之后继续向下移动,当在环中绕满一圈时记录的数值就是结点的数目n。
这里需要两个指针,我们知道链表还是一个链表,只是需要有两个指针来进行遍历,因此采取的方式是:
ListNode p1=pHead;
ListNode p2=pHead;
然后分别对p1,p2进行向下移动遍历,返回时还是返回pHead,即链表还是只有一条的。
特殊情况:
当输入结点为null时,返回null;
当输入单结点时返回null;
当链表没有环时—即要求NodesNumberOfLoop方法能判断出没有环的情况
当链表是一个首尾相连的大环时,要求先判断if(p1==p2) break;再移动p1=p1.next;p2=p2.next;因为可能p1通过移动n后直接就在环的入口结点了。
//给定一个链表,如果这个链表有环找出环的入口结点
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
//特殊的输入
if (pHead==null) return null;
//计算得到环中结点的数目
intnodesNumberOfLoop=this.NodesNumberOfLoop(pHead);
//如果没有环,直接返回null
if(nodesNumberOfLoop==0)return null;
//如果有环,并且已知环的结点数目为n,来找环的入口结点
ListNode p1=pHead;
ListNode p2=pHead;
//指针p1先走n步
for(inti=0;i<nodesNumberOfLoop;i++){
p1=p1.next;
}
//两个指针开始一起走
while(true){
//注意:这里必须先判断p1==p2;如果链表是一个收尾相连的整个环,那么当p1先走n步后其实p1已经又回到了环的入口,这个结点就是入口
if(p1==p2) break;
p1=p1.next;
p2=p2.next;
}
return p1;
}
//先找出链表中环的结点数目
public intNodesNumberOfLoop(ListNode pHead){
ListNode pfast=pHead;
ListNode pslow=pHead;
int nodesNumberOfLoop=0;
ListNode meetingNode=null;
//先找出两个指针的相遇点meetingNode
//只要是环就不会为null,但是现在还没有确定是否有环
while(true){
//如果遍历时发现没有环,则返回环的大小为0,之后再作处理。注意:return回直接结束方法
if(pfast==null||pslow==null)return 0;
//连续用next可能会有空指针异常
if(pfast.next==null)return 0;
pfast=pfast.next.next;
pslow=pslow.next;
//初始时指针都在头结点,因此pfast==pslow必然满足,因此必须先移动后再比较
if(pfast==pslow){
//当指针相遇,记录为meetingNode,当前pslow所在位置就是相遇点
meetingNode=pslow;
//结束循环
break;
}
}
//已知meetingNode,求出环的大小;pslow还在相遇点,保留meetingNode,对pslow继续进行遍历
//常识:条件语句放在条件块或者循环体中其实是一样的
while(true){
//初始时,pslow==meetingNode必然成立,因此必须先移动再判断
pslow=pslow.next;
nodesNumberOfLoop++;
if(pslow==meetingNode)break;
}
return nodesNumberOfLoop;
}
}
- 数据结构与算法分析笔记与总结(java实现)--链表7:含环链表找环入口结点问题
- 数据结构与算法分析笔记与总结(java实现)--链表6:两个链表找公共结点问题
- 数据结构与算法分析笔记与总结(java实现)--链表8:对排序链表删除重复结点问题
- 数据结构与算法分析笔记与总结(java实现)--链表9:有序环形链表中插入新结点问题
- 数据结构与算法分析笔记与总结(java实现)--链表13:每k个结点逆序问题
- 数据结构与算法分析笔记与总结(java实现)--链表14:删除链表中所有指定值结点问题
- 数据结构与算法分析笔记与总结(java实现)--二叉树8:寻找错误结点练习题
- 数据结构与算法分析笔记与总结(java实现)--链表2:倒数第k个结点问题(k从1开始)
- 数据结构与算法分析笔记与总结(java实现)--链表10:输入某个结点删除单向链表中的该结点
- 数据结构与算法分析笔记与总结(java实现)--链表3:链表反转问题
- 数据结构与算法分析笔记与总结(java实现)--链表4:单调链表合并问题
- 数据结构与算法分析笔记与总结(java实现)--链表11:链表按值分化问题
- 数据结构与算法分析笔记与总结(java实现)--链表15:链表回文判断问题
- 数据结构与算法分析笔记与总结(java实现)--链表17:无环单链表判断是否相交问题
- 数据结构与算法分析笔记与总结(java实现)--链表18:有环单链表判断是否相交问题
- 数据结构与算法分析笔记与总结(java实现)--链表19:判断单链表是否相交问题
- 数据结构与算法分析笔记与总结(java实现)--二叉树18:二叉树的下一个结点
- 数据结构与算法分析笔记与总结(java实现)--二叉树21:二叉搜索树的第k个结点
- 【笔记】Python3.X笔记
- python中文分词库结巴使用示例
- LeetCode 475. Heaters
- 【bzoj1143】[CTSC2008]祭祀river
- 持续集成篇之SVN版本管理系统的安装(CentOS+Subversion+Apache+Jsvnadmin)
- 数据结构与算法分析笔记与总结(java实现)--链表7:含环链表找环入口结点问题
- Android应用出错 error: Error retrieving parent for item: No resource found that matches the
- spring mvc入门
- C++ Qt Game Tutorial 1 - Drawing the Player (rectangle)
- NOI 2014 魔法森林 LCT
- 推背图第四十三象
- 判断是鼠标拖拽还是点击
- CCF 2015 3-2 数字排序
- 数据结构与算法分析笔记与总结(java实现)--链表8:对排序链表删除重复结点问题