两个链表相交问题

链表相交问题

判断两个链表进行相交,其中这两个链表又有可能是有环的,也有可能是无环的,这里种情况的判断逻辑不一样,所以我们要先进行判断。

判断链表是否有环

判断一个链表是否有环,有两种情况可以实现。
第一种方法,一值是把这个链表放入HashSet种,然后再判断,把next放入set中,如果next为null那就是无环,最后指向null。如果是添加到HasHSet失败,那么是set中有相同元素则有环,其中添加失败那个点就是入环节点。这种方法较简单,就不过多分析了,代码也很简单,主要看下面这种情况。

第二种情况,是最常用的情况,就是使用快慢双指针,慢指针和快指针从head开始,慢指针走一步,快指针走两步。如果快指针在行走过程中为null则就是无环,若快慢指针进行相遇了,那么就说明有环,只要把快指针放回head,把它的步数调到1,再次相遇时就是入环节点。这是经典的追赶问题,感兴趣的可以自己网上找证明。

判断是否环的代码

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

        Node fast = head.next.next;
        Node slow = head.next;

        while (fast != slow){
            if (fast.next.next == null || fast.next == null){
                return null;
            }else {
                fast = fast.next.next;
                slow = slow.next;
            }
        }

        fast = head;

        while(fast != slow){
            fast = fast.next;
            slow = slow.next;
        }

        return fast;
    }

判断完链表是否有环了,我们就可以进行分情况讨论,

在开始讨论时先明确两个链表相交后,一定只有一条路劲,因为相交节点为同一个节点,而又只有一个next指针,那么肯定只有一条路劲。

无环情况
在这个前提下,我们知道,相交后只有一个路劲。主体思想是这样的,先遍历两个链表统计长度,或者获取原先的链表在插入时维护的长度也可以。计算出它们的差值,先让长链表去走差值的步数,然后两个再一起走,过程中出现节点相等则为相交。
在这里插入图片描述
如果一起途中相等那肯定相交,如果无,那就没有相交。

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

        Node cur1 = head1;
        int n1 = 0;
        Node cur2 = head2;
        int n2 = 0;
        while(cur1.next != null){
            n1++;
            cur1 = cur1.next;
        }
        
        while(cur2.next != null){
            n2++;
            cur2 = cur2.next;
        }
        
        //最后节点都不相同肯定是无相交
        if (cur1 != cur2){
            return null;
        }
        
        //重新赋值
        cur1 = n1 - n2 > 0 ? head1 : head2;
        cur2 = cur1 == head1 ? head2 : head1;
        
        
        int n = Math.abs(n1 - n2);
        
        //先走差值步
        while (n != 0){
            n--;
            cur1 = cur1.next;
        }
        
        //来到这判断已经是有相交的,不然已经return了 再一起走找相交
        while(cur1 != cur2){
            cur1 = cur1.next;
            cur2 = cur2.next;
        }
        
        return cur1;
    }

若一个有环,一个无环
其实这种可能并不存在,因为前面,已经说了若两个链表相交,后面肯定同一路劲,不可能有这种情况。要么都有环,要么都无环

两个都有环
这里又分为3种情况
1,入环节点为0个,就是不相交情况。
在这里插入图片描述

2,入环节点为一个

在这里插入图片描述
3,入环节点有两个
在这里插入图片描述

对于情况2,因为它和上面的无环相交问题的性质是一样的,它在入环前已经,相交,前面的相交就可以把它看作无环相交,

情况3只要走一圈,判断过程种节点是否相等,如果有和另外一个链表的入环节点相交那就是情况3,无就是情况1.

  //l1为第一个入环节点 l2为第2个入环接待你
    public Node bothLoop(Node head1,Node head2,Node l1,Node l2){
        if (head1 == null || head2 == null){
            return null;
        }
        
        if (l1 == l2){//情况2只有一个节点
            return noLoop(head1,head2);
        }else {
            Node cur1 = l1.next;
            
            //走一圈
            while(cur1 != l1){
                //与另一个入环节点相交 情况3
                if (cur1 == l2){
                    return l1;
                }
                
                cur1 = cur1.next;
            }
            //情况1
            return null;
        }
    }

主方法

 public boolean isIntersect(Node h1,Node h2){
        Node l1 = getLoopNode(h1);
        Node l2 = getLoopNode(h2);
        
        //无环情况
        if (l1 == null && l2 == null){
            return noLoop(h1,h2) != null;
        }
        
        //有环情况
        if (l1 != null && l2 != null){
            return bothLoop(h1,h2,l1,l2) != null;
        }
        
        return false;
    }

以上就是关于两链表相交的全部内容.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值