两个链表是否相交问题

给定两个单链表的头节点 headAheadB ,请找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。注意:可能会出现链式结构中出现环。

首先,判断单个链表是否成环,给定一个链表,返回链表开始入环的第一个节点。 从链表的头节点开始沿着 next 指针进入环的第一个节点为环的入口节点。如果链表无环,则返回 null

很简单,快慢指针,如果成环,一定会在环内相遇,此时让fast=head,再各自一人走一步,一定会在成环位置相遇。

    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;
    }

下面分类讨论情况。

情况1,两个链表都不成环,即链表中没有环结构

cura和curb分别遍历自己的链表,并用n记录二者长度的差值。

之后,谁更长谁作cura,否则就为curb,长的先走n的长度,之后再一起走,一定会在相交位置相遇。

    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;
    }

情况2:一个为空,一个不为空

即一个成环,一个不成环,很显然,这种情况一定不相交。

情况3:都不为空

即两个链表都成环,又分为三种情况

第一种:都成环,各自不相交

 第二种,在成环前相交

第三种,相交,且成环位置不相同

 

三种情况中,情况二最好区分,因为和环就没关系,他们是在成环之前就相交了,甚至可以并到没有环的情况,下面判断情况一三

此时,要么是两链表不相交,要么就是两个入环节点不相同,那么我让其中一个入环节点转一圈,如果在转圈途中,遇到了另一个入环节点,就是情况三,否则就是情况一:,请看代码 

    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;
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值