《剑指offer》刷题——【链表】面试题23:链表中环的入口结点(java实现)
一、题目描述
如果一个链表中包含环,如何找出环的入口节点
二、题目分析:
- 要找到链表中环的入口结点,首先链表要成环,故首要任务是判断链表是否成环
- 判断链表是否成环的思路:
(1)双指针,初始值都指向头指针,一个快指针(一次移动两步),一个慢指针(一次移动一步)
(2)停止条件:快指针==慢指针,此时证明链表是带环的单向链表
(3)特殊情况:1)若链表为空,即head=null,则无环
2)fast先到尾部,则无环 - 链表头到环入口点 = (n-1)循环内环 + 相遇点到环入口点(参考于《java程序员面试笔试宝典》 P238)
- 链表环入口思路:
(1)双指针,链表头指针、相遇点指针
(2)每次各走一步,两个指针必定相遇,且相遇第一点为换入口点
三、代码实现:
public boolean IsLoop(Node head){
Node fast = head;
Node slow = head;
if(fast == null){
return false;
}
while(fast!=null && fast.next!=null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
return true;
}
}
return !(fast==null || fast.next==null);
}
public boolean FindLoopPort(Node head){
Node fast = head;
Node slow = head;
while(fast!=null && fast.next!=null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
break;
}
}
if(fast==null || fast.next==null){
return null;
}
slow = head;
while(slow != fast){
slow = slow.next;
fast = fast.next;
}
return slow;
}
方法二:
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
if(pHead==null){
return null;
}
ListNode meetNode = IsLoop(pHead);
if(meetNode == null){
return null;
}
int nodeInLoop = 1;
ListNode tmpNode = meetNode;
while(tmpNode.next != meetNode){
tmpNode = tmpNode.next;
nodeInLoop++;
}
tmpNode = pHead;
for(int i=0; i<nodeInLoop; i++){
tmpNode = tmpNode.next;
}
ListNode tmpNode2 = pHead;
while(tmpNode != tmpNode2){
tmpNode = tmpNode.next;
tmpNode2 = tmpNode2.next;
}
return tmpNode;
}
public ListNode IsLoop(ListNode pHead)
{
if(pHead==null){
return null;
}
ListNode slow = pHead;
ListNode fast = slow.next;
if(fast == null){
return null;
}
while(slow!=null && fast!=null){
if(fast == slow){
return fast;
}
fast = fast.next;
slow = slow.next;
if(fast!= null){
fast = fast.next;
}
}
return null;
}
}