引言
這個問題一種常想到的方法就是兩層循環遍歷,外層循環遍歷鏈表A,對A中每個節點,遍歷鏈表B,如果在B中找到,說明這個節點是第一個公共節點,但是這樣的方法時間復雜為mn,一般是不允采用的
分析問題
所以我們需要分析更深層次的問題,找到其中的規律,我們如果動手畫一下一般的鏈表圖就能夠發現兩個鏈表的第一個公共節點之后的樣子一定是如下表示(由此可以發現有時候動手是很重要的)
可以發現兩個鏈表在第一個節點重合之后不會再分開了
簡單多說一句不會分開的原因,因為單向鏈表的節點只有一個nextNode指向下一個節點,那么如果該節點重合了,那么后面的節點一定是同一個
如果直觀點對這個圖形進行解釋就是兩個鏈表重合之后呈現一個Y型而不是一個X型
解決問題
一般這種問題要用兩個類似指針的東西,一個先走,一個后走
所以我們先遍歷找到兩個鏈表的長度m和n,如果m大,m比n大多少,比如說k,那么先讓m先走k步,然后n和m再一起走
ListNode findFirstCommonNode(ListNode root1, ListNode root2) {
ListNode resultNode = null;
int length1 = getLength(root1);
int length2 = getLength(root2);
ListNode LongList;
ListNode ShortList;
int steps = 0;
if (length1 > length2) {
LongList = root1;
ShortList = root2;
steps = length1 - length2;
} else {
LongList = root2;
ShortList = root1;
steps = length2 - length1;
}
for (int i = 0; i < steps; i++) {
LongList = LongList.nextNode;
}
while (LongList != null && ShortList != null && LongList != ShortList) {
LongList = LongList.nextNode;
ShortList = ShortList.nextNode;
}
resultNode = LongList;
return resultNode;
}
測試代碼
public static void main(String[] args) {
ListNode head1=new ListNode();
ListNode second1=new ListNode();
ListNode third1=new ListNode();
ListNode forth1=new ListNode();
ListNode fifth1=new ListNode();
ListNode head2=new ListNode();
ListNode second2=new ListNode();
ListNode third2=new ListNode();
ListNode forth2=new ListNode();
head1.nextNode=second1;
second1.nextNode=third1;
third1.nextNode=forth1;
forth1.nextNode=fifth1;
head2.nextNode=second2;
second2.nextNode=forth1;
third2.nextNode=fifth1;
head1.data=1;
second1.data=2;
third1.data=3;
forth1.data=6;
fifth1.data=7;
head2.data=4;
second2.data=5;
third2.data=6;
forth2.data=7;
FindFirstCommonNode test=new FindFirstCommonNode();
System.out.println(test.findFirstCommonNode(head1, head2).data);
}