目录
题目描述
如果一个链表中包含环,如何找出环的入口节点?例如,在如下图所示的链表中,环的入口节点是节点3。
测试用例
- 功能测试(链表中包含或者不包含环;链表中有多个或者只有一个节点)
- 特殊输入测试(链表头节点为空指针)
题目考点
- 考察应聘者对链表的理解。
- 考察应聘者所写代码的鲁棒性(考虑的全面性)。
- 考察应聘者分析问题的能力。把一个问题分解成多个简单的步骤,是一种常用的解决复杂问题的方法。
解题思路
- 确定一个链表中包含环
用两个指向头节点指针,同时从链表的头节点触发,一个指针一次走一步,另一个指针一次走两步。如果走得快的指针追上了走得慢的指针,那么链表就包含环,如果的走得快的指针走到了链表的末尾都没有追上走得慢的指针,那么链表就不包含环。
- 找到环的入口
用两个指向头节点指针P1,P2,如果链表中的环有n个节点,则一个指针P1指针先向前移动n步,然后两个指针以相同的数据向前移动。当P2指向指向环的入口节点时,P1已经围绕环走了一圈,又回到了入口节点。
3、计算环中节点数目
两个相遇的指针一定在环中,从这个节点出发,一边继续向前移动一边计数,再次回到这个节点时,可以得。
自己解题
没思路(两个指针还能这么用,wtf)
参考解题
/*
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);
if(meetingNode == null ){
return null;
}
// 求环中节点数,nodesinLoop
int nodesinLoop = 1;
ListNode node = meetingNode;
while(node.next != meetingNode){
node = node.next;
++nodesinLoop;
}
// 根据环中节点数,找环切入口
ListNode p1 = pHead;
ListNode p2 = pHead;
for(int i = 0 ; i < nodesinLoop; ++i){
//先移动p1,nodesinLoop步
p1 = p1.next;
}
while(p1 != p2){
//再同时移动p1、p2,直到两者相遇,相遇时为环切入口
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
// -----功能模块,求环中相遇节点---------------------
public ListNode MeetingNode(ListNode pHead){
//异常处理
if(pHead == null || pHead.next == null){
return null;
}
// 快慢指针定义
ListNode slow = pHead.next;
ListNode fast = slow.next;
// 操作:判断是否有环,快2步,慢1步,直到相遇
while(slow != null && fast != null){
// 有环,返回相遇节点
if(fast == slow){
return fast;
}
slow = slow.next;
fast = fast.next;
if(fast.next != null){ // 增强 鲁棒性
fast = fast.next;
}
}
// 遍历完没相遇,没环
return null;
}
}