题目描述
输入一个包含环的链表,如何找到环的入口节点?
思路:
1, 先确定链表中是否包含环(用快慢指针的方法)
一个指针 slow
每次走一步,另一个指针 fast
每次走两步。
如果fast
指针追上了slow
指针,也就是两个指针指向了同一个节点,则说明链表包含环。
2, 找到环的入口
2.1 先得到环的大小,通过第一步已经找到了环,只要让一个指针在原地,另一个指针绕一圈来和它重逢,则绕圈圈的大小k
就是环的大小。
2.2 之后,让一个指针指向链表开头,第二个指针指向链表的第k
个节点。两个指针同时向后移动,当他们重逢时,相遇的那个节点就是环的入口节点。
以上思路的代码
// 找到环的入口
public static ListNode EntryNodeOfLoop(ListNode head){
ListNode hasLOOP = FindLoop(head);
if(hasLOOP == null){
return null;
}
// 找出环的大小
ListNode node1 = hasLOOP;
ListNode node2 = hasLOOP.next;
System.out.println("环:"+hasLOOP);
int loopCount = 1;
while(node1 != node2){
node2 = node2.next;
loopCount ++;
}
System.out.println("环大小:"+loopCount);
// 一个指针指向第k个
node2 = head;
for(int i=0;i<loopCount;i++){
node2 = node2.next;
}
node1 = head;
while(node2 != node1){
node1 = node1.next;
node2 = node2.next;
}
return node1;
}
// 判断是否有环
public static ListNode FindLoop(ListNode head){
ListNode fastNode = null;
ListNode slowNode = null;
if(head == null){
return null;
}
slowNode = head;
fastNode = head.next;
while(slowNode!=null && fastNode!=null){
if(fastNode == slowNode){
return fastNode;
}
slowNode = slowNode.next;
fastNode = fastNode.next;
if(fastNode != null){
fastNode = fastNode.next;
}
}
return null;
}
一个简洁版,参考leetcode对代码进行了一些优化
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head==null || head.next==null) return null;
ListNode fist = head;
ListNode second = head.next;
boolean isLoop = false;
while(second!=null && fist!= null){
if(fist == second){
isLoop = true;break;
}
else{
if(second.next==null) break;
fist=fist.next;
second=second.next.next;
}
}
if(isLoop){
second = head;
fist = fist.next;
while(fist != second){
second = second.next;fist = fist.next;
}
return second;
}
return null;
}
}
链表结构
public class ListNode {
public int val;
public ListNode node = null;
public ListNode next = null;
public ListNode(int val) {
this.val = val;
}
int n= 0;
public String toString(){
ListNode re = this;
String s = "";
while(re != null){
n++;
s += re.val+" -> ";
re = re.next;
if(n==5){
break;
}
}
return s;
}
}
测试结果:
备注:感觉这篇博客总结得不错,加个链接吧查看