牛客網高頻演算法題系列-BM10-兩個連結串列的第一個公共結點
題目描述
輸入兩個無環的單向連結串列,找出它們的第一個公共結點,如果沒有公共節點則返回空。(注意因為傳入資料是連結串列,所以錯誤測試資料的提示是用其他方式顯示的,保證傳入資料是正確的)
原題目見:BM10 兩個連結串列的第一個公共結點
解法一:雙重迴圈
使用雙重迴圈遍歷2個連結串列,簡單粗暴,不過效率稍低。
解法二:雙指標法
使用2個指標l1和l2分別從連結串列一和連結串列二的頭結點遍歷,遍歷到尾部後,再分別從連結串列二和連結串列一遍歷,如果兩個連結串列有公共交點,則l1和l2一定會在交點處相遇,否則,l1和l2分別遍歷完兩個連結串列後都是null,沒有公共結點。
程式碼
public class Bm010 {
/**
* 方法一:雙重迴圈
*
* @param pHead1 連結串列一
* @param pHead2 連結串列二
* @return
*/
public static ListNode findFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if (pHead1 == null || pHead2 == null) {
return null;
}
ListNode node1 = pHead1;
// 外層迴圈遍歷連結串列一的結點
while (node1 != null) {
ListNode node2 = pHead2;
// 內層迴圈遍歷連結串列二的結點
while (node2 != null) {
if (node2 == node1) {
return node1;
}
node2 = node2.next;
}
node1 = node1.next;
}
return null;
}
/**
* 雙指標法
*
* @param pHead1
* @param pHead2
* @return
*/
public static ListNode findFirstCommonNode2(ListNode pHead1, ListNode pHead2) {
// l1和l2分別從連結串列一和連結串列二的頭結點遍歷,遍歷到尾部後,再分別從連結串列二和連結串列一遍歷
ListNode l1 = pHead1, l2 = pHead2;
while (l1 != l2) {
l1 = (l1 == null) ? pHead2 : l1.next;
l2 = (l2 == null) ? pHead1 : l2.next;
}
// 如果兩個連結串列有公共交點,則l1和l2一定會在交點處相遇,此時l1就是公共結點
// 否則,l1和l2分別遍歷完兩個連結串列後都是null,沒有公共結點,返回null
return l1;
}
public static void main(String[] args) {
ListNode pHead1 = ListNode.testCase2();
System.out.println("連結串列一為");
ListNode.print(pHead1);
ListNode pHead2 = ListNode.testCase1();
pHead2.next.next.next = pHead1.next.next;
System.out.println("連結串列二為");
ListNode.print(pHead2);
ListNode.print(findFirstCommonNode(pHead1, pHead2));
ListNode.print(findFirstCommonNode2(pHead1, pHead2));
}
}
$1.01^{365} ≈ 37.7834343329$
$0.99^{365} ≈ 0.02551796445$
相信堅持的力量!