劍指offer第二版面試題23:連結串列中環的入口節點(java)
阿新 • • 發佈:2019-01-25
題目描述:
如果一個連結串列中包含環,如何找出環的入口節點?
分析:
可以用兩個指標來解決這個問題。先定義兩個指標P1和P2指向連結串列的頭結點。如果連結串列中環有n個結點,指標P1在連結串列上向前移動n步,然後兩個指標以相同的速度向前移動。當第二個指標指向環的入口結點時,第一個指標已經圍繞著環走了一圈又回到了入口結點。
剩下的問題就是如何得到環中結點的數目。我們可以使用一快一慢的兩個指標。如果兩個指標相遇,表明連結串列中存在環。兩個指標相遇的結點一定是在環中。可以從這個結點出發,一邊繼續向前移動一邊計數,當再次回到這個結點時就可以得到環中結點數了。
程式碼如下:
/**
* 連結串列中環的入口節點
*
* 思路:
* 1.判斷是否存在環,並找到快慢兩個指標相遇的位置
* 2.根據找到的這個相遇位置,統計環中節點的數目n,先讓快指標走n步,然後快慢兩個指標一起運動,快慢指標相遇時的節點就是環的入口節點
*/
public class EnterNodeInLink {
public ListNode getEnterNode(ListNode head){
//引數校驗
if(head == null){
return null;
}
//如果有環,第一個和第二個指標在環中相遇時的節點
ListNode meetingNode = meetingNode(head);
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 = head; //第一個指標
ListNode behind = head; //第二個指標
while(ringLength > 0){
ahead = ahead.next; //第一個指標先在連結串列上向前移動ringLength步
ringLength--;
}
while(ahead != behind){
ahead = ahead.next;
behind = behind.next;
}
return behind;
}
//在連結串列存在環的情況下,找到一快一慢兩個指標相遇的節點
public ListNode meetingNode(ListNode head){
//引數校驗
if(head == null){
return null;
}
ListNode behind = head.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;
}
public static void main(String[] args) {
EnterNodeInLink test = new EnterNodeInLink();
ListNode head = new ListNode();
ListNode temp1 = new ListNode();
ListNode temp2 = new ListNode();
ListNode temp3 = new ListNode();
ListNode temp4 = new ListNode();
ListNode temp5 = new ListNode();
head.value=1;
temp1.value=2;
temp2.value=3;
temp3.value=4;
temp4.value=5;
temp5.value=6;
head.next=temp1;
temp1.next=temp2;
temp2.next=temp3;
temp3.next=temp4;
temp4.next=temp5;
temp5.next=null;
ListNode resultNode = test.getEnterNode(head);
if(resultNode != null){
System.out.println(resultNode.value);
}else{
System.out.println("您輸入的引數有誤!");
}
}
}
class ListNode{
int value;
ListNode next;
}