【LeetCode160】相交鏈表三種解法

問題描述

👉相交鏈表👈題目跳轉

如下面的兩個鏈表:

【情況一】

【情況二】

【情況三】

編寫一個程序,找到兩個單鏈表相交的起始節點

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是相同的,每次兩個指針所走的步長是相同的,我們把相遇點理解爲終點,兩個兩表最終會相遇。

Picture1png

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;
        }    
    }
}

【參考鏈接】

  1. belinda題解

  2. Krahets題解

  3. 相交鏈表[3種解法]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章