劍指offer每日一題算法題(java解法)
方便日後複習,從今天開始。
算法之行始於足下
[編程題]兩個鏈表的第一個公共節點-- Java實現
------------------------------------------------------------------------------------------------------
題目描述
輸入兩個鏈表,找出它們的第一個公共結點。
前提:
理解什麼是公共節點,公共節點的意思就是當前節點值相等,且後面的子鏈表值和長度一一對應相等
解題思路:
方法一
最直觀就是暴力法,在第一鏈表上順序遍歷每個節點,每遍歷到一個節點,就在第二個鏈表上順序遍歷每個節點。如果在第二個鏈表上有一個節點和第一個鏈表上的節點一樣,則說明兩個鏈表在這個節點上重合,但是這種方法的複雜度爲O(m∗nm * nm∗n)(第一個鏈表長度爲m,第二個鏈表的長度爲n)
方法二
如果兩個鏈表存在公共節點,那麼公共節點出現在兩個鏈表的尾部。如果我們從兩個鏈表的尾部開始往前比較,那麼最後一個相同的節點就是我們要找的節點。但是這兩個鏈表是單向的,要實現尾節點最先比較,我們可以藉助兩個輔助棧。分別將兩個鏈表的節點放入兩個棧中,這樣棧頂就是兩個鏈表的尾節點,比較兩個棧頂節點是否相同,如果相同,將棧頂彈出比較下一個棧頂,直到找到最後一個相同的棧頂。時間複雜度O(m + n)。
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
import java.util.Stack;
public class Solution {
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.push(pHead1);
pHead1=pHead1.next;
}
while(pHead2!=null){
pStack2.push(pHead2);
pHead2=pHead2.next;
}
ListNode tmp=null;
while(!pStack1.isEmpty()&&!pStack2.isEmpty()){
ListNode pH1=pStack1.pop();
ListNode pH2=pStack2.pop();
if(pH1.val==pH2.val){
tmp=pH1;
}else{
break;
}
}
return tmp;
}
}
方法三
先獲得兩個鏈表的長度,然後在較長的鏈表上先走若干步(兩鏈表長度之差),接着同時在兩個鏈表上遍歷,找到的第一個相同的節點就是他們的第一個公共節點。時間複雜度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;
}