剑指Offer对答如流系列 - 链表中环的入口节点
Posted jefferychenxiao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指Offer对答如流系列 - 链表中环的入口节点相关的知识,希望对你有一定的参考价值。
面试题23:链表中环的入口节点
问题描述
一个链表中包含环,如何找出环的入口结点?例如,在图中的链表中,环的入口结点是结点3。
链表的结构
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
问题分析
首先不能忽略链表中不包含环的情况,第一件事情必须先确定链表是否有环:我们可以使用两个引用,一个跑的快、一个跑的慢,同时出发,跑的快的追上跑的慢的自然说明有环。(术语是常说的快慢引用)
如果链表有环,第二件事是确定链表中的环节点的个数,在第一件事情中,快引用追上了慢引用,以追上的位置为起点(肯定在环中),走一圈,边走边计数。
现在问题转换为求 链表中倒数第k个结点。k的值为链表中环的长度。
问题解答
public ListNode entryNodeOfLoop(ListNode head) {
// 判断是否有环
ListNode meetingNode=meetingNode(head);
if(meetingNode==null) {
return null;
}
//计算环中结点的数目
int count=1;
ListNode pNode1 = meetingNode.next;
while(pNode1!=meetingNode){
count++;
pNode1=pNode1.next;
}
// 求链表中倒数第k个结点
pNode1=head;
for(int i=1;i<=count;i++) {
pNode1=pNode1.next;
}
ListNode pNode2=head;
while(pNode1!=pNode2) {
pNode1=pNode1.next;
pNode2=pNode2.next;
}
return pNode1;
}
private ListNode meetingNode(ListNode head) {
if(head==null) {
return null;
}
ListNode pSlow=head;
ListNode pFast=head;
while(pFast!=null) {
pSlow=pSlow.next;
pFast=pFast.next;
if(pFast!=null) {
pFast=pFast.next;
}
if(pSlow!=null && pSlow==pFast) {
return pSlow;
}
}
return null;
}
以上是关于剑指Offer对答如流系列 - 链表中环的入口节点的主要内容,如果未能解决你的问题,请参考以下文章