Whether two linked lists intersect

Posted by pchytil on Mon, 24 Jan 2022 02:13:02 +0100

Given the head nodes headA and headB of two single linked lists, please find and return the starting node where the two single linked lists intersect. If two linked lists have no intersection, null is returned. Note: there may be rings in the chain structure.

First, judge whether a single linked list is a ring. Given a linked list, return the first node of the linked list into the ring. Starting from the head node of the linked list, the first node entering the ring along the next pointer is the entry node of the ring. If the linked list is acyclic, null is returned.

It's very simple. The fast and slow pointers, if they form a ring, will meet in the ring. At this time, let fast=head, take another step each, and they will meet in the ring position.

    public ListNode detectCycle(ListNode head) {
        if(head==null || head.next == null || head.next.next ==null){
            return null;
        }
        ListNode slow = head.next;
        ListNode fast = head.next.next;
        while(slow!=fast && fast!=null && fast.next!=null){
            slow = slow.next;
            fast = fast.next.next;
        }
        if(slow==fast){
            fast = head;
            while(fast!=slow){
                fast = fast.next;
                slow = slow.next;
            }
            return fast; 
        }
        return null;
    }

The situation is discussed in categories below.

In case 1, the two linked lists are not linked, that is, there is no ring structure in the linked list

cura and curb traverse their linked lists respectively, and record the difference between their lengths with n.

After that, whoever is longer will make cura, otherwise it will be curb. If it is long, go the length of n first, and then go together, you will meet at the intersection.

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode cura = headA;
        ListNode curb = headB;
        int n = 0;
        while(cura.next!=null){
            cura = cura.next;
            n++;
        }
        while(curb.next!=null){
            curb = curb.next;
            n--;
        }
        if(cura!=curb){
            return null;
        }
        cura = n > 0 ? headA : headB;
        curb = cura==headA ? headB : headA;
        n = Math.abs(n);
        while(n-->0){
            cura = cura.next;
        }
        while(cura!=curb){
            cura = cura.next;
            curb = curb.next;
        }
        return curb;
    }

Case 2: one is empty and the other is not empty

That is, one forms a ring and one does not form a ring. Obviously, this situation must not intersect.

Case 3: none is empty

That is, the two linked lists are linked, which can be divided into three cases

The first one: they all form rings and do not intersect each other

Second, intersect before forming a ring

Third, intersect and form different ring positions

 

Among the three cases, case 2 is the best to distinguish, because it has nothing to do with the ring. They intersect before forming the ring, and even there is no ring. Here is case 1 and 3

At this time, either the two linked lists do not intersect, or the two ring entry nodes are different, so I let one of the ring entry nodes turn around. If I encounter another ring entry node on the way around, it is case 3, otherwise it is case 1: please see the code

    public static ListNode bothLoop(ListNode head1, ListNode loop1, ListNode head2, ListNode loop2) {
        ListNode cur1 = null;
        ListNode cur2 = null;
        if (loop1 == loop2) {
            cur1 = head1;
            cur2 = head2;
            int n = 0;
            while (cur1 != loop1) {
                n++;
                cur1 = cur1.next;
            }
            while (cur2 != loop2) {
                n--;
                cur2 = cur2.next;
            }
            cur1 = n > 0 ? head1 : head2;
            cur2 = cur1 == head1 ? head2 : head1;
            n = Math.abs(n);
            while(n-->0){
                cur1 = cur1.next;
            }
            while(cur1!=cur2){
                cur1 = cur1.next;
                cur2 = cur2.next;
            }
            return cur1;
        }else{
            cur1 = loop1.next;
            while(cur1!=loop1){
                if(cur1 == loop2){
                    return loop1;
                }
                cur1 = cur1.next;
            }
            return null;
        }
    }

Topics: data structure leetcode linked list p2p