给定一个单链表,判断其中是否有环,已经是一个比较老同时也是比较经典的问题,在网上搜集了一些资料,
然后总结一下大概可以涉及到的问题,以及相应的解法。
首先,关于单链表中的环,一般涉及到一下问题:
1.给一个单链表,判断其中是否有环的存在;
2.如果存在环,找出环的入口点;
3.如果存在环,求出环上节点的个数;
4.如果存在环,求出链表的长度;
5.如果存在环,求出环上距离任意一个节点最远的点(对面节点);
6.(扩展)如何判断两个无环链表是否相交;
7.(扩展)如果相交,求出第一个相交的节点;
问题1:
给一个单链表,判断是否有环?
采用快慢指针的方法,慢指针每次走一个节点,快指针每次走两个节点。
type Node struct { data int next *Node } func findLoop(head *Node) bool { slow := head fast := head while(fast.next != nil && slow != nil) { slow = slow.next fast = fast.next.next if(slow == fast) { return true } } }
问题2: 环的入口
如图证明,因此,如果fast从相遇点每次一节点开始,slow从起点开始,一定在节点相遇。
func findLoopStart(head *Node) *Node { slow := head fast := head while(fast.next != nil && slow != nil) { slow = slow.next fast = fast.next.next if(slow == fast) { beak; } } if(fast.next == nil || slow == nil) { return nil //没有环 } slow := head while(slow != fast) { slow = slow.next fast = fast.next } return slow }
问题3:如果存在环,求出环上节点的个数
找到相遇点之后,再重新走一圈
问题4:如果存在环,求出链表的长度;
找到交点后,即可得出
问题5:如果存在环,求出环上距离任意一个节点最远的点(对面节点);
已确定有环,在环上任意一点A,记录下这一点之后,slow,fast以此节点为开始节点,slow每次一步,fast每次两步。
当fast走到节点A时,slow正好走到A对应的最远节点。