目录
1 题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
2 解题思路
首先我们不难想到,遍历一遍单链表,若某一结点的next指向null,则说明该单链表无环,返回null;若有环,我们定义两个引用fast和slow,让fast每次走两步,slow每次走一步,它俩肯定会在某个结点处相遇,那么问题来了,我们如何求得这个结点呢?其实不难,画个图分析一下就出来了:
相遇时,fast经过的节点个数时slow的2倍(与走了几圈无关~),此时我们假设链表总的结点数为n,头结点到入环结点的结点个数是x,入环节点到相遇结点的结点数是y,则我们不难得出:2(x+y) = n+y -> x+x+y+y = n+y -> x+x+y = n+y;即相遇结点后的部分结点总数为x,那么此时我们将slow结点置为头结点,slow和fast走x步,就可以到达相遇的结点处啦~如下图所示:
3 代码实现
public Node ExceCycle(){
Node fast = this.head;
Node slow = this.head;
while (fast != null&&fast.next != null){
//fast走两步,slow走一步
fast = fast.next.next;
slow = slow.next;
//若有环,退出循环
if (fast == slow){
break;
}
}
//当上面while条件不满足时,即该链表没有换环
if (fast == null&&fast.next == null){
return null;
}
//将slow置为头结点
slow = this.head;
while (fast != slow){
//fast走一步,slow走一步,若相遇,则退出循环
slow = slow.next;
fast = fast.next;
}
return slow;
}