1. 程式人生 > >劍指offer第二版面試題23:連結串列中環的入口節點(java)

劍指offer第二版面試題23:連結串列中環的入口節點(java)

題目描述:
如果一個連結串列中包含環,如何找出環的入口節點?

分析:
可以用兩個指標來解決這個問題。先定義兩個指標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; }