題目描述
輸入兩個鏈表,找出它們的第一個公共結點。
節點類:
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
分析
首先要理解什么是公共節點,並不是兩個節點的值相同就是公共節點。
而是在第一鏈表和第二鏈表中都存在一個節點,該節點往后的子鏈表在兩個鏈表中是相同的。
如下圖中鏈表6 - 7就是兩個鏈表的公共鏈表,而節點6就是第一個公共節點。
方法一
最直觀就是暴力法,在第一鏈表上順序遍歷每個節點,每遍歷到一個節點,就在第二個鏈表上順序遍歷每個節點。如果在第二個鏈表上有一個節點和第一個鏈表上的節點一樣,則說明兩個鏈表在這個節點上重合,但是這種方法的復雜度為O(
)(第一個鏈表長度為m,第二個鏈表的長度為n)
方法二
如果兩個鏈表存在公共節點,那么公共節點出現在兩個鏈表的尾部。如果我們從兩個鏈表的尾部開始往前比較,那么最后一個相同的節點就是我們要找的節點。但是這兩個鏈表是單向的,要實現尾節點最先比較,我們可以借助兩個輔助棧。分別將兩個鏈表的節點放入兩個棧中,這樣棧頂就是兩個鏈表的尾節點,比較兩個棧頂節點是否相同,如果相同,將棧頂彈出比較下一個棧頂,直到找到最后一個相同的棧頂。時間復雜度O(m + n)。
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if(pHead1 == null || pHead2 == null) {
return null;
}
Stack<ListNode> pStack1 = new Stack<ListNode>();
Stack<ListNode> pStack2 = new Stack<ListNode>();
while(pHead1 != null) {
pStack1.add(pHead1);
pHead1 = pHead1.next;
}
while(pHead2 != null) {
pStack2.add(pHead2);
pHead2 = pHead2.next;
}
ListNode temp = null;
while(!pStack1.isEmpty() && !pStack2.isEmpty()) {
ListNode pH1 = pStack1.pop();
ListNode pH2 = pStack2.pop();
if(pH1.val == pH2.val) {
temp = pH1;
}
else {
break;
}
}
return temp;
}
方法三
先獲得兩個鏈表的長度,然后在較長的鏈表上先走若干步(兩鏈表長度之差),接着同時在兩個鏈表上遍歷,找到的第一個相同的節點就是他們的第一個公共節點。時間復雜度O(m + n)。
public ListNode FindFirstCommonNode_2(ListNode pHead1, ListNode pHead2) {
if(pHead1 == null || pHead2 == null) {
return null;
}
int pHead1Length = getListLength(pHead1);
int pHead2Length = getListLength(pHead2);
int gap = pHead1Length - pHead2Length;
ListNode tempList1 = pHead1;
ListNode tempList2 = pHead2;
if(pHead2Length > pHead1Length) {
tempList1 = pHead2;
tempList2 = pHead1;
gap = pHead2Length - pHead1Length;
}
for (int i = 0; i < gap; i++) {
tempList1 = tempList1.next;
}
while((tempList1 != null) && (tempList2 != null) && (tempList1.val != tempList2.val)) {
tempList1 = tempList1.next;
tempList2 = tempList2.next;
}
return tempList1;
}
public int getListLength(ListNode list) {
int number = 0;
while(list != null) {
++number;
list = list.next;
}
return number;
}
方法四
很玄學的代碼。。。
用兩個指針掃描”兩個鏈表“,最終兩個指針到達 null 或者到達公共結點。
public ListNode FindFirstCommonNode_3(ListNode pHead1, ListNode pHead2) {
if(pHead1 == null || pHead2 == null) {
return null;
}
ListNode temp1 = pHead1;
ListNode temp2 = pHead2;
while(temp1 != temp2) {
temp1 = (temp1 == null ? pHead2 : temp1.next);
temp2 = (temp2 == null ? pHead1 : temp2.next);
System.out.println(pHead1.val);
}
return temp1;
}