本文參考自《劍指offer》一書,代碼採用Java語言。html
更多:《劍指Offer》Java實現合集 java
輸入兩個鏈表,找出它們的第一個公共結點。post
蠻力法:遍歷第一個鏈表的結點,每到一個結點,就在第二個鏈表上遍歷每一個結點,判斷是否相等。時間複雜度爲O(m*n),效率低;測試
使用棧:因爲公共結點出如今尾部,因此用兩個棧分別放入兩個鏈表中的結點,從尾結點開始出棧比較。時間複雜度O(m+n),空間複雜度O(m+n)。this
利用長度關係:計算兩個鏈表的長度之差,長鏈表先走相差的步數,以後長短鏈表同時遍歷,找到的第一個相同的結點就是第一個公共結點。url
利用兩個指針:一個指針順序遍歷list1和list2,另外一個指針順序遍歷list2和list1,(這樣兩指針可以保證最終同時走到尾結點),兩個指針找到的第一個相同結點就是第一個公共結點。指針
測試算例 htm
1.功能測試(有/無公共結點;公共結點分別在鏈表的中間,頭結點和尾結點)blog
2.特殊測試(頭結點爲null)get
//題目:輸入兩個鏈表,找出它們的第一個公共結點。 public class FirstCommonNodesInLists { public class ListNode{ int val; ListNode next = null; ListNode(int val) { this.val = val; } } //方法1:利用長度關係 public ListNode findFirstCommonNode1(ListNode pHead1, ListNode pHead2) { int length1 = getLength(pHead1); int length2 = getLength(pHead2); int lengthDif = length1-length2; ListNode longList = pHead1; ListNode shortList = pHead2; if(lengthDif<0){ longList = pHead2; shortList = pHead1; lengthDif = -lengthDif; } for(int i=0;i<lengthDif;i++) longList = longList.next; while(longList!=null && longList!=shortList ){ longList=longList.next; shortList=shortList.next; } return longList; //沒有公共結點恰好是null } private int getLength(ListNode head){ int len=0; while(head!=null){ len++; head=head.next; } return len; } //方法2:兩個指針,p1順序遍歷list1和list2;p2順序遍歷list2和list1;最終必定會相遇 public ListNode findFirstCommonNode2(ListNode pHead1, ListNode pHead2) { ListNode p1=pHead1; ListNode p2=pHead2; while(p1!=p2){ p1= p1==null ? pHead2 : p1.next; p2= p2==null ? pHead1 : p2.next; } return p1; } }
1.因爲有共同結點時,後面的鏈表是重合的,因此這道題關鍵是要保證最後同時遍歷到達尾結點,所以就有了後面三種方法:
利用棧的先進後出實現同時到達;
利用長度關係,長鏈表先行幾步,實現同時到達;
兩個指針同時遍歷兩個鏈表,一個先list1後list2,另外一個則相反,也能夠實現同時到達。