問題描述
👉相交鏈表👈題目跳轉
如下面的兩個鏈表:
【情況一】
【情況二】
【情況三】
編寫一個程序,找到兩個單鏈表相交的起始節點
1. 最直觀:暴力求解
對鏈表A中的每一個結點nodeA,遍歷整個鏈表 B
。並檢查鏈表 B
中是否存在結點nodeB和nodeA相同(注意不是數值相等)
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null) {
return null;
}
while(headA != null) {
ListNode p = headB;
while(p != null) {
if(p == headA) {
return p;
} else{
p = p.next;
}
}
headA = headA.next;
}
return null;
}
}
2. 愛情浪漫相遇法
一種比較巧妙的方式是,分別爲鏈表A和鏈表B設置指針A和指針B,然後開始遍歷鏈表,如果遍歷完當前鏈表,則將指針指向另外一個鏈表的頭部繼續遍歷,直至兩個指針相遇。
最終兩個指針分別走過的路徑爲:
-
指針A:a+c+b
-
指針B :b+c+a
-
明顯
a+c+b = b+c+a
,因而如果兩個鏈表相交,則指針A和指針B必定在相交結點相遇。
思路理解:
思路是設定兩個指針分別指向兩個鏈表頭部,一起向前走直到其中一個到達末端,另一個與末端距離則是兩鏈表的 長度差。再通過長鏈表指針先走的方式消除長度差,最終兩鏈表即可同時走到相交點。
兩個指針在遍歷鏈表時,總路徑都是a+b+c是相同的,每次兩個指針所走的步長是相同的,我們把相遇點理解爲終點,兩個兩表最終會相遇。
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode ha = headA, hb = headB;
while (ha != hb) {
ha = ha != null ? ha.next : headB;
hb = hb != null ? hb.next : headA;
}
return ha;
}
}
入棧解法
將兩個鏈表分別進行壓棧操作,之後進行對比出棧,當元素一致時就不斷出出出,不一致就停止出棧操作,之後開始判斷兩個棧是否爲空的情況,分別討論應該返回哪個元素
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null) {
return null;
}
Stack<ListNode> st1 = new Stack<>();
Stack<ListNode> st2 = new Stack<>();
ListNode nodeA = headA;
ListNode nodeB = headB;
while(nodeA != null) {
st1.push(nodeA);
nodeA = nodeA.next;
}
while(nodeB != null) {
st2.push(nodeB);
nodeB = nodeB.next;
}
ListNode t1 = st1.peek();
ListNode t2 = st2.peek();
//在沒有彈出元素之前,棧頂元素一定相同,否則兩鏈表沒有相交
if(t1 != t2)
return null;
//兩個棧都不爲空開始彈棧
while(t1 == t2 && !st1.empty() && !st2.empty()) {
t1 = st1.peek();
st1.pop();
t2 = st2.peek();
st2.pop();
}
//一個空一個不爲空
if(st1.empty() && !st2.empty()) {
//如果棧此時已空直接返回next
if(t1 != t2)
return t2.next;
else {
//如果棧不空
t2 = st2.peek();
st2.pop();
return t2.next;
}
} else if(!st1.empty() && st2.empty()) {
if(t1 != t2) {
return t1.next;
} else {
t1 = st1.peek();
st1.pop();
return t1.next;
}
} else if(st2.empty() && st1.empty()) {
//兩個棧都空
if(t1 == t2)
return t1;
return t2.next;
} else {
//兩個棧都不爲空
return t1.next;
}
}
}
【參考鏈接】