两个单链表相交,找出第一个交点

题目

给两个单链表,如何判断两个单链表是否相交?若相交,则找出第一个相交的节点

理解

解这道题之前,我们需要首先明确一个概念: 
如果两个单链表有共同的节点,那么从第一个共同节点开始,后面的节点都会重叠,直到链表结束

因为两个链表中有一个共同节点,则这个节点里的指针域指向的下一个节点地址一样,所以下一个节点也会相交,依次类推。所以,若相交,则两个链表呈“Y”字形。如下图:

解法

暴力解法 

从头开始遍历第一个链表,遍历第一个链表的每个节点时,同时从头到尾遍历第二个链表,看是否有相同的节点,第一次找到相同的节点即第一个交点。若第一个链表遍历结束后,还未找到相同的节点,即不存在交点。时间复杂度为O(n^2)。

使用栈

从头遍历两个链表。创建两个栈,第一个栈存储第一个链表的节点,第二个栈存储第二个链表的节点。每遍历到一个节点时,就将该节点入栈。两个链表都入栈结束后。则通过top判断栈顶的节点是否相等即可判断两个单链表是否相交。因为我们知道,若两个链表相交,则从第一个相交节点开始,后面的节点都相交。 
若两链表相交,则循环出栈,直到遇到两个出栈的节点不相同,则这个节点的后一个节点就是第一个相交的节点。


        // 单链表l1
        LinkedList<String> l1 = new LinkedList<>();
        l1.add("a");
        l1.add("b");
        l1.add("c");
        l1.add("d");
        l1.add("e");
        l1.add("f");
 
        // 单链表l2
        LinkedList<String> l2 = new LinkedList<>();
        l2.add("c1");
        l2.add("d1");
        l2.add("e");
        l2.add("f");
 
        /* 栈特性:后进先出 */
        // 将l1元素压入s1栈中
        Stack s1 = new Stack();
        s1.addAll(l1);
 
        // 将l2元素压入s2栈中
        Stack s2 = new Stack();
        s2.addAll(l2);
 
        String temp = null;
        /* s3栈存放所有相交节点 */
        Stack s3 = new Stack();
        while (!s1.empty() && !s2.empty()) {
            /* peek方法获取第一个元素 */
            temp = (String) s1.peek();
            /* pop方法出栈 */
            if ((s1.pop()).equals(s2.pop())) {
                s3.add(temp);
            } else {
                break;
            }
        }
 
        if(!s3.empty()) {
            System.out.println("两个单链表相交,且相交的第一个节点,值为:\t" + s3.peek());
            System.out.println(s3);
        }

遍历链表记录长度

同时遍历两个链表到尾部,同时记录两个链表的长度。若两个链表最后的一个节点相同,则两个链表相交。 
有两个链表的长度后,我们就可以知道哪个链表长,设较长的链表长度为len1,短的链表长度为len2。 
则先让较长的链表向后移动(len1-len2)个长度。然后开始从当前位置同时遍历两个链表,当遍历到的链表的节点相同时,则这个节点就是第一个相交的节点


        // 单链表l1
        LinkedList<String> l1 = new LinkedList<>();
        l1.add("a");
        l1.add("b");
        l1.add("c");
        l1.add("d");
        l1.add("e");
        l1.add("f");
 
        // 单链表l2
        LinkedList<String> l2 = new LinkedList<>();
        l2.add("c1");
        l2.add("d1");
        l2.add("e");
        l2.add("f");
 
        int ls1 = l1.size();
        int ls2 = l2.size();
 
        /* 判断l1与l2是否相交 */
        if(l1.get(ls1-1).equals(l2.get(ls2-1))) {
            System.out.println("两个单链表相交");
        }
 
        /* 获取相交节点 */
        List ret = new ArrayList();
        for(int i=0; i<ls2; i++) {
            if(l2.get(i).equals(l1.get(i + (ls1-ls2)))) {
                ret.add(l2.get(i));
            }
        }
 
        System.out.println("相交的第一个节点为:\t" + ret.get(0));
 

发布了60 篇原创文章 · 获赞 9 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_37876078/article/details/105584322