算法通关村第一关-----链表经典问题之解决两个链表第一个公共子节点问题

问题描述

算法通关村第一关-----链表经典问题之解决两个链表第一个公共子节点问题_第1张图片

如图所示,两个链表A和B,头节点已知,存在公共子节点c1,c1的位置和数量是不确定的,要求找到A,B的第一个公共子节点。详见leetcode

方法一 基于哈希和集合实现

方法描述

将其中一个链表存储在哈希或者集合中,遍历另一个链表,判断当前遍历结点是否存在于哈希或者集合中,如存在,即是第一个公共子结点,如遍历结束,仍未找到,则不存在公共子节点

代码实现

public static LinkedNode getIntersectionNode(LinkedNode headA, LinkedNode headB){
        HashSet<LinkedNode> hashSet = new HashSet<LinkedNode>();
        while (headA!=null){
            hashSet.add(headA);
            headA = headA.next;
        }
        while (headB!=null){
            if (hashSet.contains(headB)){
                return headB;
            }
            headB = headB.next;
        }
        return null;
    }

方法二 基于栈实现

方法描述

将两个链表分别压入两个栈中,之后将栈中元素依次出栈,比较是否相同,如相同,记录当前元素,继续遍历,直至不相同之前的最后一个相同元素就是公共子节点,如第一次出栈比较就不相同,说明没有公共子节点

代码实现

public static LinkedNode getIntersectionNode(LinkedNode headA, LinkedNode headB){
        Stack<LinkedNode> stackA = new Stack();
        Stack<LinkedNode> stackB = new Stack();
        while (headA!=null){
            stackA.push(headA);
            headA = headA.next;
        }
        while (headB!=null){
            stackB.push(headB);
            headB = headB.next;
        }
        LinkedNode intersectionNode = null;
        while (stackA.size()>0&& stackB.size()>0){
            if(stackA.peek() == stackB.peek()){
                intersectionNode = stackA.pop();
                stackB.pop();
            }
            else {
                break;
            }
        }
        return intersectionNode;
    }

方法三 基于拼接字符串实现

方法描述

以上图的A、B链表为例

A:a1、a2、c1、c2、c3

B:b1、b2、b3、c1、c2、c3

可以在A之后拼接B,B之后拼接A,

AB:a1、a2、c1、c2、c3、b1、b2、b3、c1、c2、c3

BA:b1、b2、b3、c1、c2、c3、a1、a2、c1、c2、c3

此时可以发现 A与B的第一个公共子节点一定存在于AB、BA自后向前的最后一个相同节点,C1

实际操作过程中的拼接使用指针指向另一个链表即可

代码实现

public static LinkedNode getIntersectionNode(LinkedNode headA, LinkedNode headB){
        LinkedNode iterA = headA;
        LinkedNode iterB = headB;
        if (headA==null||headB==null){
            return null;
        }

        while(iterA != iterB){
            iterA = iterA.next;
            iterB = iterB.next;
            if (iterA == null){
                iterA = headB;
            }
            if (iterB == null){
                iterB = headA;
            }
        }
        return iterA;
    }

方法四 基于差和双指针实现

方法描述

假设A的长度为La,B的长度为Lb,差为|La-Lb|,可以遍历长的链表指针先遍历|La-Lb|,之后两个指针一起遍历,遍历到的第一个相同节点即为第一个公共子节点

代码实现

public static LinkedNode getIntersectionNode4(LinkedNode headA, LinkedNode headB) {
        LinkedNode iterA = headA;
        LinkedNode iterB = headB;
        int la = 0;
        int lb = 0;
        while (iterA != null) {
            la++;
            iterA = iterA.next;
        }
        while (iterB != null) {
            lb++;
            iterB = iterB.next;
        }
        int l = la > lb ? la - lb : lb - la;
        iterA = headA;
        iterB = headB;
        if (la > lb) {
            for (int i = 0; i < l; i++) {
                iterA = iterA.next;
            }
        }
        if (la < lb) {
            for (int i = 0; i < l; i++) {
                iterB = iterB.next;
            }
        }
        while (iterA!=null&&iterB!=null) {
            if (iterA == iterB){
                return iterA;
            }
            iterA = iterA.next;
            iterB = iterB.next;
        }
        return null;
    }

你可能感兴趣的:(算法训练营,算法,链表,数据结构)