两个单链表相交的问题

发布于:2023-09-16 ⋅ 阅读:(76) ⋅ 点赞:(0)

两链表相交及其第一个节点 

 

判断有环无环

判断有无环,如果有环返回第一个入环节点,如果无环返回null

使用额外空间:Set结构

沿着指针将a、b、c、d、e、c放入set结构中,每次放入前查看在set集合中是否存在;

若遍历到null都没有重复节点,那么链表为无环链表;

若有重复,链表有环,第一个重复的值即为第一个入环节点

不使用额外空间

如果一个链表无环,一定能够指向null

如果一个链表有环,最终它一定在一直循环

快慢指针:快指针一次走两步,慢指针一次走一步

如果一个链表无环,快指针先指向null

如果一个链表有环,快满指针一定会在某一时刻相遇

(不一定在入环节点相遇并且慢指针在环中转的圈数不超过两圈

相遇之后,慢指针在原地,快指针回到起点,接下来快慢指针都走一步,两个指针一定会在入环节点相遇(数学证明)

//判断有环无环,有环返回第一个入环节点,无环返回null
    public static Node getloopNode(Node head) {

        if (head == null || head.next == null || head.next.next == null) {
            return null;
        }

        //快慢指针相遇的时候停止,如果快慢指针都从head出发,开始时相遇,所以快指针先走两步,慢指针走一步
        Node slow = head.next;
        Node fast = head.next.next;
        while (slow != fast) {
            if (fast.next == null || fast.next.next == null) {//无环
                return null;
            }

            slow = slow.next;
            fast = fast.next.next;
        }

        fast = head;//回到开头
        while (slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }

        return slow;
    }

对两个链表分类讨论

两个链表分别调用getloopNode方法

两个无环单链表

        loop1 == null        loop2 == null

        不可能如左图所示,单链表只能有一个next指针;如果两链表相交,一定是右图所示

                     

      先遍历两个链表,记录两链表的长度;

      比较链表最后一个Node,如果相等,则两链表相交;若不相等,则两链表不相交

      长链表先走两个链表之间的长度差,之后两链表再一起走,两链表在第一个相交节点处相遇  

//如果两个链表都无环,判断两链表是否相交,相交则返回第一个相交节点,不相交则返回null
    public static Node noLoop(Node head1, Node head2) {
        if (head1 == null || head2 == null) {
            return null;
        }

        int length1 = 0, length2 = 0;
        //遍历链表1
        while (head1.next != null) {//链表1在最后一个节点停
            length1++;
            head1 = head1.next;
        }
        //遍历链表2
        while (head2.next != null) {//链表2在最后一个节点停
            length2++;
            head2 = head2.next;
        }

        if (head1 == head2) {//不相交
            return null;
        } else {
            while(head1 != head2){//还没相遇
                if (length1 > length2) {//链表1较长
                    length1--;
                    head1 = head1.next;
                    
                } else if (length1 < length2) {//链表2较长
                    length2--;
                    head2 = head2.next;

                } else {//长链表先走了差值长度之后,两链表一起走直到相遇
                    head1 = head1.next;
                    head2 = head2.next;
                }
            }
        }
        
        return head1;
    }

一个有环单链表,一个无环单链表 

此种情况两链表不可能相交,一定会有某个节点有两个next指针

两个有环单链表

                                                      

情况2:求相交节点 = 两无环单链表求相交节点

             把入环节点看成结尾,终止节点为loop1==loop2

情况1和情况3:loop1继续向下走,如果在循环中没有遇到loop2,则两链表不相交;

                         如果在循环的过程中遇到了loop2,则两链表相交

                         返回的结果既可以是loop1,也可以是loop2,两个节点都是两链表的相交节点

//如果两个链表都有环,判断两链表是否相交,相交则返回第一个相交节点,不相交则返回null
    //loop1 = getloopNode(head1);   loop2 = getloopNode(head2);
    public static Node bothLoop(Node head1, Node head2, Node loop1, Node loop2) {

        if (loop1 == loop2) {//情况2

            int length1 = 0, length2 = 0;
            //遍历链表1
            while (head1.next != null) {//链表1在最后一个节点停
                length1++;
                head1 = head1.next;
            }
            //遍历链表2
            while (head2.next != null) {//链表2在最后一个节点停
                length2++;
                head2 = head2.next;
            }

            if (head1 == head2) {//不相交
                return null;
            } else {
                while (head1 != head2) {//还没相遇
                    if (length1 > length2) {//链表1较长
                        length1--;
                        head1 = head1.next;

                    } else if (length1 < length2) {//链表2较长
                        length2--;
                        head2 = head2.next;

                    } else {//长链表先走了差值长度之后,两链表一起走直到相遇
                        head1 = head1.next;
                        head2 = head2.next;
                    }
                }
            }
            return head1;

        } else {//情况1和情况3

            Node temp = loop1.next;
            while (temp != loop1) {//在圈里面遍历

                if (temp == loop2) {//遇到loop2,情况3
                    return loop1;//return loop2;
                }
                temp = temp.next;
            }

            return null;//情况1
        }
    }

回到题目

调用 

public static Node getIntersectNode(Node head1,Node head2){
        if(head1 == null || head2 == null){
            return null;
        }

        Node loop1 = getloopNode(head1);
        Node loop2 = getloopNode(head2);
        if(loop1 == null && loop2 == null){
            return noLoop(head1,head2);
        } else if (loop1 != null && loop2 != null) {
            return bothLoop(head1,head2,loop1,loop2);
        }else{
            return null;
        }
    }

 全代码

package linkedlist;

public class IntersectLinkedList {
    class Node {
        public int value;
        public Node next;

        public Node(int data) {
            this.value = data;
        }

    }

    //判断有环无环,有环返回第一个入环节点,无环返回null
    public static Node getloopNode(Node head) {

        if (head == null || head.next == null || head.next.next == null) {
            return null;
        }

        //快慢指针相遇的时候停止,如果快慢指针都从head出发,开始时相遇,所以快指针先走两步,慢指针走一步
        Node slow = head.next;
        Node fast = head.next.next;
        while (slow != fast) {
            if (fast.next == null || fast.next.next == null) {//无环
                return null;
            }

            slow = slow.next;
            fast = fast.next.next;
        }

        fast = head;//回到开头
        while (slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }

        return slow;
    }


    //如果两个链表都无环,判断两链表是否相交,相交则返回第一个相交节点,不相交则返回null
    public static Node noLoop(Node head1, Node head2) {
        if (head1 == null || head2 == null) {
            return null;
        }

        int length1 = 0, length2 = 0;
        //遍历链表1
        while (head1.next != null) {//链表1在最后一个节点停
            length1++;
            head1 = head1.next;
        }
        //遍历链表2
        while (head2.next != null) {//链表2在最后一个节点停
            length2++;
            head2 = head2.next;
        }

        if (head1 == head2) {//不相交
            return null;
        } else {
            while (head1 != head2) {//还没相遇
                if (length1 > length2) {//链表1较长
                    length1--;
                    head1 = head1.next;

                } else if (length1 < length2) {//链表2较长
                    length2--;
                    head2 = head2.next;

                } else {//长链表先走了差值长度之后,两链表一起走直到相遇
                    head1 = head1.next;
                    head2 = head2.next;
                }
            }
        }

        return head1;
    }


    //如果两个链表都有环,判断两链表是否相交,相交则返回第一个相交节点,不相交则返回null
    //loop1 = getloopNode(head1);   loop2 = getloopNode(head2);
    public static Node bothLoop(Node head1, Node head2, Node loop1, Node loop2) {

        if (loop1 == loop2) {//情况2

            int length1 = 0, length2 = 0;
            //遍历链表1
            while (head1.next != null) {//链表1在最后一个节点停
                length1++;
                head1 = head1.next;
            }
            //遍历链表2
            while (head2.next != null) {//链表2在最后一个节点停
                length2++;
                head2 = head2.next;
            }

            if (head1 == head2) {//不相交
                return null;
            } else {
                while (head1 != head2) {//还没相遇
                    if (length1 > length2) {//链表1较长
                        length1--;
                        head1 = head1.next;

                    } else if (length1 < length2) {//链表2较长
                        length2--;
                        head2 = head2.next;

                    } else {//长链表先走了差值长度之后,两链表一起走直到相遇
                        head1 = head1.next;
                        head2 = head2.next;
                    }
                }
            }
            return head1;

        } else {//情况1和情况3

            Node temp = loop1.next;
            while (temp != loop1) {//在圈里面遍历

                if (temp == loop2) {//遇到loop2,情况3
                    return loop1;//return loop2;
                }
                temp = temp.next;
            }
        }
        return null;//情况1
    }

    public static Node getIntersectNode(Node head1,Node head2){
        if(head1 == null || head2 == null){
            return null;
        }

        Node loop1 = getloopNode(head1);
        Node loop2 = getloopNode(head2);
        if(loop1 == null && loop2 == null){
            return noLoop(head1,head2);
        } else if (loop1 != null && loop2 != null) {
            return bothLoop(head1,head2,loop1,loop2);
        }else{
            return null;
        }
    }
    

}




本文含有隐藏内容,请 开通VIP 后查看