
两链表相交及其第一个节点
 
判断有环无环
判断有无环,如果有环返回第一个入环节点,如果无环返回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;
        }
    }
    
}



















