25链表中环的入口节点–剑指offer,java版
题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
分析:
①首先判断是否有环:设置两个指针,一个一次走一步,另一个一次走两步,如果走的快的指针追上了走的慢的指针(即两个指针在环中相遇),说明有环,返回相遇的那个节点。
②求出这个环的长度:设置一个临时指针等于相遇的这个节点,再移动此节点,当此节点又等于临时指针时,说明已走完一个回路,可求得其长度
③从头节点开始,先让第一个指针移动 环的长度 步,再同时移动两指针,当两指针相等时,即为入口节点
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
//参数校验
if(pHead == null){
return null;
}
//如果有环,第一个和第二个指针在环中相遇时的节点
ListNode meetingNode = meetingNode(pHead);
int ringLength = 0; //环的长度
if(meetingNode != null){ //如果存在环,就求出环的长度
ListNode tempNode = meetingNode;
meetingNode = meetingNode.next;
while(meetingNode != tempNode){
ringLength++;
meetingNode = meetingNode.next;
}
ringLength++;
}else{ //如果不存在环,就返回null
return null;
}
ListNode ahead = pHead; //第一个指针
ListNode behind = pHead; //第二个指针
while(ringLength > 0){
ahead = ahead.next; //第一个指针先在链表上向前移动ringLength步
ringLength--;
}
while(ahead != behind){
ahead = ahead.next;
behind = behind.next;
}
return behind;
}
//在链表存在环的情况下,找到一快一慢两个指针相遇的节点
public ListNode meetingNode(ListNode pHead){
//参数校验
if(pHead == null){
return null;
}
ListNode behind = pHead.next; //后面的指针
//如果只有一个节点直接返回null
if(behind == null){
return null;
}
ListNode ahead = behind.next; //前面的指针
while(behind != null && ahead != null){
if(behind == ahead){
return ahead;
}
//behind指针在链表上移动一步
behind = behind.next;
//ahead指针在链表上移动两步
ahead = ahead.next;
if(ahead != null){
ahead = ahead.next;
}
}
return null;
}
}