两链表是否有环+是否相交

1. 分析

来源:《程序员代码面试指南》(第2版)左程云

  1. 单链表是否有环
  2. 如果一个有环,一个没有,则肯定不想交
  3. 如果都没有环,找到相交点,参考
  4. 如果都有环,分三种情况:
    • 情况一,环入口一致,相交点在入口前面
    • 情况二,环入口不一致,且loop1 loop2在环中不连通,则不相交
    • 请款三,环入口不一致,且loop1 loop2在环中连通,则两个入口都算相交点

2. 代码

public class IntersectList(){
    public 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);
        }
        //如果都有环
        if(loop1 != null && loop2 != null){
            return bothLoop(head1,head2);
        }
        //如果一个有环,一个没有,则肯定不想交
        return null;
    }
    public Node getLoopNode(Node head){
        //链表中是否有环,环的入口
        if(head == null ||head.next == null) return null;
          Node node1 = head;
          Node node2 = head;
          while(node1!=null && node1.next!=null){
              //先寻找是否有环
              //快慢指针一起出发
              node1 = node1.next.next;
              node2 = node2.next;
              if(node1 == node2){//如有环,快慢指针在环中某个结点相遇
                  //使用同速的双指针,找到环的入口
                  //起点分别是head和环中相遇点
                  node2=pHead;
                  while(node1 != node2){
                      node1= node1.next;
                      node2 = node2.next;
                  }
                  return node1;
              }         
          }
          return null;
    }
    public Node noLoop(Node head1, Node head2,Node tail = null){
        //两链表都没环,找相交结点
        //若相交则从相交的结点到tail是相同的
        //@param tail表示表尾,默认为空,可初始化未非空值,方便复用
        if(head1 == null || head2 = null){
            return null;
        }
        int n = 0;
        Node cur1 = head1;
        Node cur2 = head2;
        //计算长度差n 
        while(cur1 != tail) {
            n++;
            cur1 = cur1.next;
        }
        while(cur2 != tail){
            n--;
            cur2 = cur2.next;
        }
        //两尾不同则不相交
        if(cur1 != cur2) return null;
        //cur1 指向长链表,cur2指向短的
        cur1 = (n > 0) ? head1 : head2;
        cur2 = (cur1 == head1) ? head2 : head1;
        //长链表先走n步
        while(n>0){
            cur1 = cur1.next;
            n--;
        }
        //两指针再一起走
        while(cur1 != cur2){
            cur1 = cur1.next;
            cur2 = cur2.next;
        }
        //相遇的第一个节点就是交点
        return cur1;
    }
    public Node bothLoop(Node head1,Node loop1, Node head2, Node loop2){
        //两链表都有环,找相交结点
        //三种情况
        //情况一,环入口一致,相交点在入口前面
        //情况二,环入口不一致,且loop1 loop2在环中不连通,则不相交
        //请款三,环入口不一致,且loop1 loop2在环中连通,则两个入口都算相交点
        Node cur1 = null;
        Node cur2 = null;
        if(loop1 == loop2 ){
            //用noLoop()找到环入口前的相交点,注意第三个参数设为环入口
            return noLoop(head1, head2, loop1);
        }else{

            for(cur1 = loop1.next; cur1 != loop1; cur1 = cur1.next){
                //情况三
                if(cur1 == loop2) return loop1;
            }
            //情况二
            return null;
        }

    }
}

3. 复杂度

空间:O(1)
时间:O(M+N)

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
正在热议
更多
# 一张图晒出你司的标语 #
4255次浏览 75人参与
# AI面会问哪些问题? #
27541次浏览 551人参与
# 开放七大实习专项,百度暑期实习值得冲吗 #
15092次浏览 221人参与
# 你的实习产出是真实的还是包装的? #
20041次浏览 342人参与
# 找AI工作可以去哪些公司? #
8950次浏览 232人参与
# 春招至今,你的战绩如何? #
64488次浏览 575人参与
# 厦门银行科技岗值不值得投 #
7945次浏览 188人参与
# 从事AI岗需要掌握哪些技术栈? #
8813次浏览 301人参与
# 你做过最难的笔试是哪家公司 #
33117次浏览 230人参与
# 中国电信笔试 #
31933次浏览 292人参与
# 投递几十家公司,到现在0offer,大家都一样吗 #
340695次浏览 2173人参与
# 哪些公司真双非友好? #
69557次浏览 289人参与
# 阿里笔试 #
178372次浏览 1314人参与
# 机械人避雷的岗位/公司 #
62693次浏览 393人参与
# 第一份工作一定要去大厂吗 #
14429次浏览 122人参与
# 金三银四,你的春招进行到哪个阶段了? #
22050次浏览 280人参与
# 为了减少AI幻觉,你注入过哪些设定? #
26232次浏览 310人参与
# 沪漂/北漂你觉得哪个更苦? #
9764次浏览 193人参与
# HR最不可信的一句话是__ #
6163次浏览 113人参与
# 应届生第一份工资要多少合适 #
20663次浏览 86人参与
# AI时代,哪个岗位还有“活路” #
11431次浏览 340人参与
# 春招你拿到offer了吗 #
831100次浏览 9986人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务