LeetCode演算法題-Intersection of Two Linked Lists(Java實現)
這是悅樂書的第178次更新,第180篇原創
01 看題和準備
今天介紹的是LeetCode演算法題中Easy級別的第37題(順位題號是160)。編寫程式以找到兩個單鏈表交叉的節點。例如:
以下兩個連結串列:
A: a1→a2
↘
c1→c2→c3
↗
B:b1→b2→b3
連結串列A和連結串列B在c1處相交。
注意:
如果兩個連結列表根本沒有交集,則返回null。
函式返回後,連結列表必須保留其原始結構。
可以假設整個連結結構中沒有任何環。
程式碼最好在O(n)時間內執行,並且只使用O(1)記憶體。
本次解題使用的開發工具是eclipse,jdk使用的版本是1.8,環境是win7 64位系統,使用Java語言編寫和測試。
02 第一種解法
這兩個單鏈表,也可以看做是兩陣列,找出其中重複元素開始位置的值,最直接的辦法就是上兩層迴圈,外層遍歷連結串列A,內層迴圈遍歷連結串列B,直到遇到相交的節點為止,否則返回空。
特殊情況:當兩連結串列中有一個為空的話,直接返回空。
public ListNode getIntersectionNode(ListNode headA, ListNode headB) { if (headA == null || headB == null) { return null; } ListNode B = headB; while (headA != null) { while (headB != null) { if (headA == headB) { return headA; } headB = headB.next; } headA = headA.next; headB = B; } return null; }
但是此種解法的時間時間複雜度是O(n^2),最壞的情況是兩連結串列的長度都是n,並且相交的節點在最後位置或者沒有相交的點。
03 第二種解法
先來看個例子,假設A和B兩人要比武,A的功夫等級是10級,B的功夫等級是8級,B覺得這樣比武不公平,就讓A把實力壓制到8級,再去和B比武,此時兩人的功夫等級都是8級,於是開始了一場驚天動地的比武...
回到此題中來,因為無法確定兩個連結串列的長度是否相等,就算兩者有交點,但是起點不一樣,還是會錯過,無法找到交點。這時,我們就需要判斷兩連結串列的長度,重新定義好起點,才能開始遍歷節點。
如果連結串列A長度大於連結串列B的長度,此時連結串列A就需要先向前移動兩者之間長度差值個節點,然後才能和B開始依次遍歷比較,反之B也是如此。
public ListNode getIntersectionNode2(ListNode headA, ListNode headB) {
int len1 = findLength(headA);
int len2 = findLength(headB);
int diff = (len1 >= len2) ? (len1 - len2) : (len2 - len1);
if (len1 >= len2) {
while (diff > 0) {
headA = headA.next;
diff--;
}
} else {
while (diff > 0) {
headB = headB.next;
diff--;
}
}
while (headA != null || headB != null) {
if (headA == headB) {
return headA;
}
headA = headA.next;
headB = headB.next;
}
return null;
}
public int findLength(ListNode head) {
int len = 0;
while (head != null) {
len += 1;
head = head.next;
}
return len;
}
04 第三種解法
還記得之前那道判斷單鏈表是否有環的題目嗎?沒錯,此題我們也可以藉助環的思路來解題。
當遍歷A連結串列時,如果遍歷到了最後一位節點,此時跳轉到B連結串列的起始節點,然後開始遍歷B連結串列;當遍歷B連結串列時,如果遍歷到了最後一位節點,此時跳轉到A連結串列的起始節點,然後開始遍歷A連結串列。此時就相當於在遍歷一條由連結串列A和連結串列B組合起來的新連結串列,如果此新連結串列存在環,那麼表示兩連結串列是有交點的,如果遍歷完都沒有碰到環,說明兩連結串列是沒有交點的。
public ListNode getIntersectionNode3(ListNode headA, ListNode headB) {
if (headA == null || headB == null) {
return null;
}
ListNode A = headA;
ListNode B = headB;
while (A != B) {
if (A != null) {
A = A.next;
} else {
A = headB;
}
if (B != null) {
B = B.next;
} else {
B = headA;
}
}
return A;
}
05 小結
此題最優解法是第三種解法,其次是第二種,最差的解法是第一種。
演算法專題目前已連續日更超過一個月,演算法題文章37+篇,公眾號對話方塊回覆【資料結構與演算法】、【演算法】、【資料結構】中的任一關鍵詞,獲取系列文章合集。
以上就是全部內容,如果大家有什麼好的解法思路、建議或者其他問題,可以下方留言交流,點贊、留言、轉發就是對我最大的回報和支援!